From a721b175c3ee6560b0a8abb0264bc950f86a4ce3 Mon Sep 17 00:00:00 2001 From: Packit Service Date: Jan 04 2021 09:53:45 +0000 Subject: m17n-lib-1.8.0 base --- diff --git a/ABOUT-NLS b/ABOUT-NLS new file mode 100644 index 0000000..83bc72e --- /dev/null +++ b/ABOUT-NLS @@ -0,0 +1,1068 @@ +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 November +2007. 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 az be bg bs ca cs cy da de el en en_GB eo + +----------------------------------------------------+ + Compendium | [] [] [] [] | + a2ps | [] [] [] [] [] | + aegis | () | + ant-phone | () | + anubis | [] | + ap-utils | | + aspell | [] [] [] [] [] | + bash | [] | + bfd | | + bibshelf | [] | + binutils | | + bison | [] [] | + bison-runtime | [] | + bluez-pin | [] [] [] [] [] | + cflow | [] | + clisp | [] [] [] | + console-tools | [] [] | + coreutils | [] [] [] [] | + cpio | | + cpplib | [] [] [] | + cryptonit | [] | + dialog | | + diffutils | [] [] [] [] [] [] | + doodle | [] | + e2fsprogs | [] [] | + enscript | [] [] [] [] | + fetchmail | [] [] () [] [] | + findutils | [] | + findutils_stable | [] [] [] | + flex | [] [] [] | + fslint | | + gas | | + gawk | [] [] [] | + gcal | [] | + gcc | [] | + gettext-examples | [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] | + gettext-tools | [] [] | + gip | [] | + gliv | [] [] | + glunarclock | [] | + gmult | [] [] | + gnubiff | () | + gnucash | [] [] () () [] | + gnuedu | | + gnulib | [] | + gnunet | | + gnunet-gtk | | + gnutls | [] | + gpe-aerial | [] [] | + gpe-beam | [] [] | + 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 | [] [] | + gretl | () | + gsasl | | + gss | | + gst-plugins-bad | [] [] | + gst-plugins-base | [] [] | + gst-plugins-good | [] [] [] | + gst-plugins-ugly | [] [] | + gstreamer | [] [] [] [] [] [] [] | + gtick | () | + gtkam | [] [] [] [] | + gtkorphan | [] [] | + gtkspell | [] [] [] [] | + gutenprint | [] | + hello | [] [] [] [] [] | + herrie | [] | + hylafax | | + idutils | [] [] | + indent | [] [] [] [] | + iso_15924 | | + iso_3166 | [] [] [] [] [] [] [] [] [] [] [] | + iso_3166_2 | | + iso_4217 | [] [] [] | + iso_639 | [] [] [] [] | + jpilot | [] | + jtag | | + jwhois | | + kbd | [] [] [] [] | + keytouch | [] [] | + keytouch-editor | [] | + keytouch-keyboa... | [] | + latrine | () | + ld | [] | + leafpad | [] [] [] [] [] | + libc | [] [] [] [] | + libexif | [] | + libextractor | [] | + libgpewidget | [] [] [] | + libgpg-error | [] | + libgphoto2 | [] [] | + libgphoto2_port | [] [] | + libgsasl | | + libiconv | [] [] | + libidn | [] [] [] | + lifelines | [] () | + lilypond | [] | + lingoteach | | + lprng | | + lynx | [] [] [] [] | + m4 | [] [] [] [] | + mailfromd | | + mailutils | [] | + make | [] [] | + man-db | [] [] [] | + minicom | [] [] [] | + nano | [] [] [] | + opcodes | [] | + parted | [] [] | + pilot-qof | | + popt | [] [] [] | + psmisc | [] | + pwdutils | | + qof | | + radius | [] | + recode | [] [] [] [] [] [] | + rpm | [] | + screem | | + scrollkeeper | [] [] [] [] [] [] [] [] | + sed | [] [] [] | + shared-mime-info | [] [] [] [] () [] [] [] | + sharutils | [] [] [] [] [] [] | + shishi | | + skencil | [] () | + solfege | | + soundtracker | [] [] | + sp | [] | + system-tools-ba... | [] [] [] [] [] [] [] [] [] | + tar | [] [] | + texinfo | [] [] [] | + tin | () () | + tuxpaint | [] [] [] [] [] [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux | [] [] [] [] | + util-linux-ng | [] [] [] [] | + vorbis-tools | [] | + wastesedge | () | + wdiff | [] [] [] [] | + wget | [] [] [] | + xchat | [] [] [] [] [] [] [] | + xkeyboard-config | [] | + xpad | [] [] [] | + +----------------------------------------------------+ + af am ar az be bg bs ca cs cy da de el en en_GB eo + 6 0 2 1 8 26 2 40 48 2 56 88 15 1 15 18 + + es et eu fa fi fr ga gl gu he hi hr hu id is it + +--------------------------------------------------+ + Compendium | [] [] [] [] [] | + a2ps | [] [] [] () | + aegis | | + ant-phone | [] | + anubis | [] | + ap-utils | [] [] | + aspell | [] [] [] | + bash | [] | + bfd | [] [] | + bibshelf | [] [] [] | + binutils | [] [] [] | + bison | [] [] [] [] [] [] | + bison-runtime | [] [] [] [] [] | + bluez-pin | [] [] [] [] [] | + cflow | [] | + clisp | [] [] | + console-tools | | + coreutils | [] [] [] [] [] [] | + cpio | [] [] [] | + cpplib | [] [] | + cryptonit | [] | + dialog | [] [] [] | + diffutils | [] [] [] [] [] [] [] [] [] | + doodle | [] [] | + e2fsprogs | [] [] [] | + enscript | [] [] [] | + fetchmail | [] | + findutils | [] [] [] | + findutils_stable | [] [] [] [] | + flex | [] [] [] | + fslint | | + gas | [] [] | + gawk | [] [] [] [] () | + gcal | [] [] | + gcc | [] | + gettext-examples | [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] | + gettext-tools | [] [] [] [] | + gip | [] [] [] [] | + gliv | () | + glunarclock | [] [] [] | + gmult | [] [] [] | + gnubiff | () () | + gnucash | () () () | + gnuedu | [] | + gnulib | [] [] [] | + gnunet | | + gnunet-gtk | | + gnutls | | + gpe-aerial | [] [] | + gpe-beam | [] [] | + 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 | [] [] [] | + gretl | [] [] [] () | + gsasl | [] [] | + gss | [] [] | + gst-plugins-bad | [] [] [] [] | + gst-plugins-base | [] [] [] [] | + gst-plugins-good | [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] | + gstreamer | [] [] [] | + gtick | [] [] [] | + gtkam | [] [] [] [] | + gtkorphan | [] [] | + gtkspell | [] [] [] [] [] [] [] | + gutenprint | [] | + hello | [] [] [] [] [] [] [] [] [] [] [] [] [] | + herrie | [] | + hylafax | | + idutils | [] [] [] [] [] | + indent | [] [] [] [] [] [] [] [] [] [] | + iso_15924 | [] | + iso_3166 | [] [] [] [] [] [] [] [] [] [] [] [] [] | + iso_3166_2 | [] | + iso_4217 | [] [] [] [] [] [] | + iso_639 | [] [] [] [] [] [] | + jpilot | [] [] | + jtag | [] | + jwhois | [] [] [] [] [] | + kbd | [] [] | + keytouch | [] [] [] | + keytouch-editor | [] | + keytouch-keyboa... | [] [] | + latrine | [] [] | + ld | [] [] [] [] | + leafpad | [] [] [] [] [] [] | + libc | [] [] [] [] [] | + libexif | [] | + libextractor | [] | + libgpewidget | [] [] [] [] [] | + libgpg-error | [] | + libgphoto2 | [] [] [] | + libgphoto2_port | [] [] | + libgsasl | [] [] | + libiconv | [] [] [] | + libidn | [] [] | + lifelines | () | + lilypond | [] [] [] | + lingoteach | [] [] [] | + lprng | | + lynx | [] [] [] | + m4 | [] [] [] [] | + mailfromd | | + mailutils | [] [] | + make | [] [] [] [] [] [] [] [] | + man-db | [] | + minicom | [] [] [] [] | + nano | [] [] [] [] [] [] [] | + opcodes | [] [] [] [] | + parted | [] [] [] | + pilot-qof | | + popt | [] [] [] [] | + psmisc | [] [] | + pwdutils | | + qof | [] | + radius | [] [] | + recode | [] [] [] [] [] [] [] [] | + rpm | [] [] | + screem | | + scrollkeeper | [] [] [] | + sed | [] [] [] [] [] | + shared-mime-info | [] [] [] [] [] [] | + sharutils | [] [] [] [] [] [] [] [] | + shishi | [] | + skencil | [] [] | + solfege | [] | + soundtracker | [] [] [] | + sp | [] | + system-tools-ba... | [] [] [] [] [] [] [] [] [] | + tar | [] [] [] [] [] | + texinfo | [] [] [] | + tin | [] () | + tuxpaint | [] [] | + unicode-han-tra... | | + unicode-transla... | [] [] | + util-linux | [] [] [] [] [] [] [] | + util-linux-ng | [] [] [] [] [] [] [] | + vorbis-tools | | + wastesedge | () | + wdiff | [] [] [] [] [] [] [] [] | + wget | [] [] [] [] [] [] [] [] | + xchat | [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] | + xpad | [] [] [] | + +--------------------------------------------------+ + es et eu fa fi fr ga gl gu he hi hr hu id is it + 85 22 14 2 48 101 61 12 2 8 2 6 53 29 1 52 + + ja ka ko ku ky lg lt lv mk mn ms mt nb ne nl nn + +--------------------------------------------------+ + Compendium | [] | + a2ps | () [] [] | + aegis | () | + ant-phone | [] | + anubis | [] [] [] | + ap-utils | [] | + aspell | [] [] | + bash | [] | + bfd | | + bibshelf | [] | + binutils | | + bison | [] [] [] | + bison-runtime | [] [] [] | + bluez-pin | [] [] [] | + cflow | | + clisp | [] | + console-tools | | + coreutils | [] | + cpio | [] | + cpplib | [] | + cryptonit | [] | + dialog | [] [] | + diffutils | [] [] [] | + doodle | | + e2fsprogs | [] | + enscript | [] | + fetchmail | [] [] | + findutils | [] | + findutils_stable | [] | + flex | [] [] | + fslint | | + gas | | + gawk | [] [] | + gcal | | + gcc | | + gettext-examples | [] [] [] | + gettext-runtime | [] [] [] | + gettext-tools | [] [] | + gip | [] [] | + gliv | [] | + glunarclock | [] [] | + gmult | [] [] [] | + gnubiff | | + gnucash | () () () | + gnuedu | | + gnulib | [] [] | + gnunet | | + gnunet-gtk | | + gnutls | [] | + gpe-aerial | [] | + gpe-beam | [] | + 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 | [] [] | + gretl | | + gsasl | [] | + gss | | + gst-plugins-bad | [] | + gst-plugins-base | [] | + gst-plugins-good | [] | + gst-plugins-ugly | [] | + gstreamer | [] | + gtick | [] | + gtkam | [] [] | + gtkorphan | [] | + gtkspell | [] [] | + gutenprint | [] | + hello | [] [] [] [] [] [] [] | + herrie | [] | + hylafax | | + idutils | [] | + indent | [] [] | + iso_15924 | [] | + iso_3166 | [] [] [] [] [] [] [] [] | + iso_3166_2 | [] | + iso_4217 | [] [] [] | + iso_639 | [] [] [] [] | + jpilot | () () | + jtag | | + jwhois | [] | + kbd | [] | + keytouch | [] | + keytouch-editor | [] | + keytouch-keyboa... | | + latrine | [] | + ld | | + leafpad | [] [] | + libc | [] [] [] | + libexif | | + libextractor | | + libgpewidget | [] | + libgpg-error | | + libgphoto2 | [] | + libgphoto2_port | [] | + libgsasl | [] | + libiconv | [] | + libidn | [] [] | + lifelines | [] | + lilypond | [] | + lingoteach | [] | + lprng | | + lynx | [] [] | + m4 | [] [] | + mailfromd | | + mailutils | | + make | [] [] [] | + man-db | | + minicom | [] | + nano | [] [] [] | + opcodes | [] | + parted | [] [] | + pilot-qof | | + popt | [] [] [] | + psmisc | [] [] [] | + pwdutils | | + qof | | + radius | | + recode | [] | + rpm | [] [] | + screem | [] | + scrollkeeper | [] [] [] [] | + sed | [] [] | + shared-mime-info | [] [] [] [] [] [] [] | + sharutils | [] [] | + shishi | | + skencil | | + solfege | () () | + soundtracker | | + sp | () | + system-tools-ba... | [] [] [] [] | + tar | [] [] [] | + texinfo | [] [] | + tin | | + tuxpaint | () [] [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux | [] [] | + util-linux-ng | [] [] | + vorbis-tools | | + wastesedge | [] | + wdiff | [] [] | + wget | [] [] | + xchat | [] [] [] [] | + xkeyboard-config | [] [] [] | + xpad | [] [] [] | + +--------------------------------------------------+ + ja ka ko ku ky lg lt lv mk mn ms mt nb ne nl nn + 51 2 25 3 2 0 6 0 2 2 20 0 11 1 103 6 + + or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta + +--------------------------------------------------+ + Compendium | [] [] [] [] [] | + a2ps | () [] [] [] [] [] [] | + aegis | () () | + ant-phone | [] [] | + anubis | [] [] [] | + ap-utils | () | + aspell | [] [] [] | + bash | [] [] | + bfd | | + bibshelf | [] | + binutils | [] [] | + bison | [] [] [] [] [] | + bison-runtime | [] [] [] [] [] | + bluez-pin | [] [] [] [] [] [] [] [] [] | + cflow | [] | + clisp | [] | + console-tools | [] | + coreutils | [] [] [] [] | + cpio | [] [] [] | + cpplib | [] | + cryptonit | [] [] | + dialog | [] | + diffutils | [] [] [] [] [] [] | + doodle | [] [] | + e2fsprogs | [] [] | + enscript | [] [] [] [] [] | + fetchmail | [] [] [] | + findutils | [] [] [] | + findutils_stable | [] [] [] [] [] [] | + flex | [] [] [] [] [] | + fslint | [] | + gas | | + gawk | [] [] [] [] | + gcal | [] | + gcc | [] [] | + gettext-examples | [] [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] [] [] | + gettext-tools | [] [] [] [] [] [] [] | + gip | [] [] [] [] | + gliv | [] [] [] [] [] [] | + glunarclock | [] [] [] [] [] [] | + gmult | [] [] [] [] | + gnubiff | () [] | + gnucash | () [] | + gnuedu | | + gnulib | [] [] [] | + gnunet | | + gnunet-gtk | [] | + gnutls | [] [] | + gpe-aerial | [] [] [] [] [] [] [] | + gpe-beam | [] [] [] [] [] [] [] | + 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 | [] [] [] [] | + gretl | [] [] [] | + gsasl | [] [] [] | + gss | [] [] [] [] | + gst-plugins-bad | [] [] [] | + gst-plugins-base | [] [] | + gst-plugins-good | [] [] | + gst-plugins-ugly | [] [] [] | + gstreamer | [] [] [] [] | + gtick | [] | + gtkam | [] [] [] [] [] | + gtkorphan | [] | + gtkspell | [] [] [] [] [] [] [] [] | + gutenprint | [] | + hello | [] [] [] [] [] [] [] [] | + herrie | [] [] [] | + hylafax | | + idutils | [] [] [] [] [] | + indent | [] [] [] [] [] [] [] | + iso_15924 | | + iso_3166 | [] [] [] [] [] [] [] [] [] [] [] [] [] | + iso_3166_2 | | + iso_4217 | [] [] [] [] [] [] [] | + iso_639 | [] [] [] [] [] [] [] | + jpilot | | + jtag | [] | + jwhois | [] [] [] [] | + kbd | [] [] [] | + keytouch | [] | + keytouch-editor | [] | + keytouch-keyboa... | [] | + latrine | | + ld | [] | + leafpad | [] [] [] [] [] [] | + libc | [] [] [] [] | + libexif | [] [] | + libextractor | [] [] | + libgpewidget | [] [] [] [] [] [] [] [] | + libgpg-error | [] [] [] | + libgphoto2 | [] | + libgphoto2_port | [] [] [] | + libgsasl | [] [] [] [] | + libiconv | [] [] [] | + libidn | [] [] () | + lifelines | [] [] | + lilypond | | + lingoteach | [] | + lprng | [] | + lynx | [] [] [] | + m4 | [] [] [] [] [] | + mailfromd | [] | + mailutils | [] [] [] | + make | [] [] [] [] | + man-db | [] [] [] [] | + minicom | [] [] [] [] [] | + nano | [] [] [] [] | + opcodes | [] [] | + parted | [] | + pilot-qof | | + popt | [] [] [] [] | + psmisc | [] [] | + pwdutils | [] [] | + qof | [] [] | + radius | [] [] | + recode | [] [] [] [] [] [] [] | + rpm | [] [] [] [] | + screem | | + scrollkeeper | [] [] [] [] [] [] [] | + sed | [] [] [] [] [] [] [] [] [] | + shared-mime-info | [] [] [] [] [] [] | + sharutils | [] [] [] [] | + shishi | [] | + skencil | [] [] [] | + solfege | [] | + soundtracker | [] [] | + sp | | + system-tools-ba... | [] [] [] [] [] [] [] [] [] | + tar | [] [] [] [] | + texinfo | [] [] [] [] | + tin | () | + tuxpaint | [] [] [] [] [] [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux | [] [] [] [] | + util-linux-ng | [] [] [] [] | + vorbis-tools | [] | + wastesedge | | + wdiff | [] [] [] [] [] [] [] | + wget | [] [] [] [] | + xchat | [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] | + xpad | [] [] [] | + +--------------------------------------------------+ + or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta + 0 5 77 31 53 4 58 72 3 45 46 9 45 122 3 + + tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu + +---------------------------------------------------+ + Compendium | [] [] [] [] | 19 + a2ps | [] [] [] | 19 + aegis | [] | 1 + ant-phone | [] [] | 6 + anubis | [] [] [] | 11 + ap-utils | () [] | 4 + aspell | [] [] [] | 16 + bash | [] | 6 + bfd | | 2 + bibshelf | [] | 7 + binutils | [] [] [] [] | 9 + bison | [] [] [] [] | 20 + bison-runtime | [] [] [] [] | 18 + bluez-pin | [] [] [] [] [] [] | 28 + cflow | [] [] | 5 + clisp | | 9 + console-tools | [] [] | 5 + coreutils | [] [] [] | 18 + cpio | [] [] [] [] | 11 + cpplib | [] [] [] [] [] | 12 + cryptonit | [] | 6 + dialog | [] [] [] | 9 + diffutils | [] [] [] [] [] | 29 + doodle | [] | 6 + e2fsprogs | [] [] | 10 + enscript | [] [] [] | 16 + fetchmail | [] [] | 12 + findutils | [] [] [] | 11 + findutils_stable | [] [] [] [] | 18 + flex | [] [] | 15 + fslint | [] | 2 + gas | [] | 3 + gawk | [] [] [] | 16 + gcal | [] | 5 + gcc | [] [] [] | 7 + gettext-examples | [] [] [] [] [] [] | 29 + gettext-runtime | [] [] [] [] [] [] | 28 + gettext-tools | [] [] [] [] [] | 20 + gip | [] [] | 13 + gliv | [] [] | 11 + glunarclock | [] [] [] | 15 + gmult | [] [] [] [] | 16 + gnubiff | [] | 2 + gnucash | () [] | 5 + gnuedu | [] | 2 + gnulib | [] | 10 + gnunet | | 0 + gnunet-gtk | [] [] | 3 + gnutls | | 4 + gpe-aerial | [] [] | 14 + gpe-beam | [] [] | 14 + gpe-calendar | [] [] | 7 + gpe-clock | [] [] [] [] | 21 + gpe-conf | [] [] [] | 16 + gpe-contacts | [] [] | 10 + gpe-edit | [] [] [] [] [] | 22 + gpe-filemanager | [] [] | 7 + gpe-go | [] [] [] [] | 19 + gpe-login | [] [] [] [] [] | 21 + gpe-ownerinfo | [] [] [] [] | 21 + gpe-package | [] | 6 + gpe-sketchbook | [] [] | 16 + gpe-su | [] [] [] [] | 21 + gpe-taskmanager | [] [] [] [] | 21 + gpe-timesheet | [] [] [] [] | 18 + gpe-today | [] [] [] [] [] | 21 + gpe-todo | [] [] | 8 + gphoto2 | [] [] [] [] | 21 + gprof | [] [] | 13 + gpsdrive | [] | 5 + gramadoir | [] | 7 + grep | [] | 12 + gretl | | 6 + gsasl | [] [] [] | 9 + gss | [] | 7 + gst-plugins-bad | [] [] [] | 13 + gst-plugins-base | [] [] | 11 + gst-plugins-good | [] [] [] [] [] | 16 + gst-plugins-ugly | [] [] [] | 13 + gstreamer | [] [] [] | 18 + gtick | [] [] | 7 + gtkam | [] | 16 + gtkorphan | [] | 7 + gtkspell | [] [] [] [] [] [] | 27 + gutenprint | | 4 + hello | [] [] [] [] [] | 38 + herrie | [] [] | 8 + hylafax | | 0 + idutils | [] [] | 15 + indent | [] [] [] [] [] | 28 + iso_15924 | [] [] | 4 + iso_3166 | [] [] [] [] [] [] [] [] [] | 54 + iso_3166_2 | [] [] | 4 + iso_4217 | [] [] [] [] [] | 24 + iso_639 | [] [] [] [] [] | 26 + jpilot | [] [] [] [] | 7 + jtag | [] | 3 + jwhois | [] [] [] | 13 + kbd | [] [] [] | 13 + keytouch | [] | 8 + keytouch-editor | [] | 5 + keytouch-keyboa... | [] | 5 + latrine | [] [] | 5 + ld | [] [] [] [] | 10 + leafpad | [] [] [] [] [] | 24 + libc | [] [] [] | 19 + libexif | [] | 5 + libextractor | [] | 5 + libgpewidget | [] [] [] | 20 + libgpg-error | [] | 6 + libgphoto2 | [] [] | 9 + libgphoto2_port | [] [] [] | 11 + libgsasl | [] | 8 + libiconv | [] [] | 11 + libidn | [] [] | 11 + lifelines | | 4 + lilypond | [] | 6 + lingoteach | [] | 6 + lprng | [] | 2 + lynx | [] [] [] | 15 + m4 | [] [] [] | 18 + mailfromd | [] [] | 3 + mailutils | [] [] | 8 + make | [] [] [] | 20 + man-db | [] | 9 + minicom | [] | 14 + nano | [] [] [] | 20 + opcodes | [] [] | 10 + parted | [] [] [] | 11 + pilot-qof | [] | 1 + popt | [] [] [] [] | 18 + psmisc | [] [] | 10 + pwdutils | [] | 3 + qof | [] | 4 + radius | [] [] | 7 + recode | [] [] [] | 25 + rpm | [] [] [] [] | 13 + screem | [] | 2 + scrollkeeper | [] [] [] [] | 26 + sed | [] [] [] [] | 23 + shared-mime-info | [] [] [] | 29 + sharutils | [] [] [] | 23 + shishi | [] | 3 + skencil | [] | 7 + solfege | [] | 3 + soundtracker | [] [] | 9 + sp | [] | 3 + system-tools-ba... | [] [] [] [] [] [] [] | 38 + tar | [] [] [] | 17 + texinfo | [] [] [] | 15 + tin | | 1 + tuxpaint | [] [] [] | 19 + unicode-han-tra... | | 0 + unicode-transla... | | 2 + util-linux | [] [] [] | 20 + util-linux-ng | [] [] [] | 20 + vorbis-tools | [] [] | 4 + wastesedge | | 1 + wdiff | [] [] | 23 + wget | [] [] [] | 20 + xchat | [] [] [] [] | 29 + xkeyboard-config | [] [] [] | 14 + xpad | [] [] [] | 15 + +---------------------------------------------------+ + 76 teams tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu + 163 domains 0 3 1 74 51 0 143 21 1 57 7 45 0 2036 + + 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 November 2007 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/AUTHORS b/AUTHORS new file mode 100644 index 0000000..9450e08 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,11 @@ +Kenichi Handa + Core developer. + +Mikiko Nishikimi + Core developer. + +Naoto Takahashi + Core developer. + +Satoru Tomura + Core developer. diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..5ab7695 --- /dev/null +++ b/COPYING @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This 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. + + This 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 this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..b069d89 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,572 @@ +2018-02-08 K. Handa + + Version 1.8.0 released. + + * configure.ac: Version changed to 1.8.0. + +2017-12-08 handa + + * .gitignore: Add TAGS. + +2016-01-12 K. Handa + + Install m17n-config only on a system that does not have pkg-config. + + * configure.ac: Make HAVE_PKG_CONFIG AM_CONDITIONAL. + + * Makefile.am (BINSCRIPTS): New variable set conditionally. + (bin_SCRIPTS): Set to the value of BINSCRIPTS. + +2015-08-29 K. Handa + + * configure.ac: Version changed to 1.7.1. + (API_VERSION): Change to 4.2.4. + +2015-04-05 K. Handa + + * m17n-config.in: Change the encoding to utf-8. + +2014-12-10 K. Handa + + * Version 1.7.0 released. + +2014-12-10 K. Handa + + * configure.ac (API_VERSION): Change to 4:1:4 (revision incremented). + +2014-11-11 K. Handa + + * .gitignore: Converted from .cvsigore. + + * .cvsignore: Delete it. + +2014-10-18 K. Handa + + * configure.ac: Version changed to 1.7.0. + +2012-09-18 Kenichi Handa + + * Version 1.6.4 released. + +2012-04-23 Kenichi Handa + + * configure.ac: Version changed to 1.6.4. + +2011-10-11 Kenichi Handa + + * Version 1.6.3 released. + +2011-09-12 Kenichi Handa + + * configure.ac: Version changed to 1.6.3. + +2011-02-21 Daiki Ueno (tiny change) + + * m17n-core.pc.in (moduledir): Use ${libdir} instead of + ${exec_prefix}/lib. + + * m17n-shell.pc.in (moduledir): Likewise. + + * m17n-flt.pc.in (moduledir): Likewise. + + * m17n-gui.pc.in (moduledir): Likewise. + +2011-01-12 Kenichi Handa + + * Version 1.6.2 released. + +2011-01-12 Kenichi Handa + + * Makefile.am: Update copyright year. + +2010-09-24 Kenichi Handa + + * configure.ac (AC_CONFIG_HEADERS): Put config.h in the top + directory (intl/*.c require it). + +2010-09-22 Kenichi Handa + + * configure.ac: Version changed to 1.6.2. + +2010-09-13 Kenichi Handa + + * configure.ac: If libotf-config is not available, try pkg-config. + +2010-09-02 Kenichi Handa + + * bootstrap.sh: Clean old files at first. + +2010-08-27 Kenichi Handa + + * .cvsignore: Add ABOUT-NLS. + + * intl/*, m4/*: Delete them. + + * po/*: All filles re-generated by gettextize. + + * config.rpath: Delete it. + + * ABOUT-NLS: Delete it. + + * configure.ac: Call AC_GNU_SOURCE and AM_GNU_GETTEXT_VERSION. + Call AC_PROG_LIBTOOL later. + + * bootstrap.sh: Make po/Makevars from po/Makevars.template. + + * Makefile.am (EXTRA_DIST): Remove m4/ChangeLog config.rpath + mkinstalldirs. + +2010-08-12 Kenichi Handa + + * configure.ac: Fix help string for --enable-gui. + +2010-04-23 Kenichi Handa + + * Version 1.6.1 released. + +2010-04-07 Kenichi Handa + + * m17n-gui.pc.in (moduledir): New variable. + + * m17n-flt.pc.in (moduledir): New variable. + + * m17n-shell.pc.in (moduledir): New variable. + + * m17n-core.pc.in (moduledir): New variable. + +2010-04-06 Kenichi Handa + + * .cvsignore: Add mkinstalldirs, ltmain.sh. + +2010-04-04 handa + + * configure.ac: Add AC_PROG_LIBTOOL. Comment out LT_PREREQ and + LT_INIT. + +2010-04-02 Kenichi Handa + + * configure.ac: Version changed to 1.6.1. + +2010-03-30 Kenichi Handa + + * Version 1.6.0 released. + +2010-03-30 Kenichi Handa + + * configure.ac: Version changed to 1.6.0. + +2010-03-19 Kenichi Handa + + * configure.ac: Version changed to 1.6.0pre. + +2010-02-18 Kenichi Handa + + * configure.ac (M17N_BINARY_VERSION): New variable. + (M17N_MODULE_DIR): New variable. AC_SUBST it. + +2009-11-05 Kenichi Handa + + * configure.ac: Check if the OTF library has OTF_drive_gpos2 (). + +2009-10-05 Kenichi Handa + + * configure.ac: Version changed to 1.6.0. + (API_VERSION): Changed to 4.0.4. + +2009-08-13 Kenichi Handa + + * Version 1.5.5 released. + +2009-07-29 Kenichi Handa + + * configure.ac: Add AC_CONFIG_MACRO_DIR([m4]). Update by + autoupdate program. + + * mkinstalldirs: Removed. + + * bootstrap.sh: Simplified by using autoreconf. + +2009-07-28 Kenichi Handa + + * configure.ac: Version changed to 1.5.5. + +2009-03-02 Kenichi Handa + + * Version 1.5.4 released. + +2009-02-25 Kenichi Handa + + * configure.ac: Version changed to 1.5.4. + +2008-10-20 Kenichi Handa + + * Version 1.5.3 released. + +2008-09-24 Kenichi Handa + + * configure.ac: Versions changed to 1.5.3. + +2008-06-23 Kenichi Handa + + * Version 1.5.2 released. + +2008-05-30 Kenichi Handa + + * configure.ac: Versions changed to 1.5.2. + +2008-01-31 Kenichi Handa + + * Version 1.5.1 released. + +2008-01-15 Kenichi Handa + + * configure.ac: Versions changed to 1.5.1. + +2007-12-28 Kenichi Handa + + * Version 1.5.0 released. + +2007-11-13 Kenichi Handa + + * configure.ac: Version changed to 1.5.0 + (API_VERSION): Updated to 3:0:3. + + * m17n-config.in: Add FLT support. + +2007-10-12 Kenichi Handa + + * m17n-flt.pc.in: Don't require m17n-shell. + +2007-08-15 Kenichi Handa + + * m17n-flt.pc.in (prefix): New file. + + * configure.ac (AC_CONFIG_FILES): Add m17n-flt.pc. + + * Makefile.am (EXTRA_DIST): Add m17n-flt.pc.in. + (BASICDATA): Add m17n-flt.pc. + +2007-07-13 Kenichi Handa + + * Version 1.4.0 released. + +2007-05-24 Kenichi Handa + + * configure.ac (HAVE_ANTHY): Use PKG_CHECK_MODULES to check it. + +2007-05-16 Kenichi Handa + + * configure.ac: Version changed to 1.4.0 + (API_VERSION): Updated to 2:0:2. + +2007-02-28 Kenichi Handa + + * configure.ac: Version changed to 1.3.5. + +2006-12-14 Kenichi Handa + + * .cvsignore: Add INSTALL, depcomp, install-sh, and missing. + +2006-12-07 TAKAHASHI Naoto + + * Update FSF postal address. + +2006-12-06 Kenichi Handa + + * Version 1.3.4 released. + +2006-09-21 Kenichi Handa + + * mkinstalldirs: New file. + + * bootstrap.sh: Don't delete mkinstalldirs. Change order of + calling auto tools. + + * ABOUT-NLS: New file. + + * intl, m4, po: New directories. + +2006-09-21 gettextize + + * Makefile.am (SUBDIRS): Add intl. + * configure.ac (AC_CONFIG_FILES): Add intl/Makefile. + +2006-09-17 gettextize + + * Makefile.am (SUBDIRS): Add po. + (ACLOCAL_AMFLAGS): New variable. + (EXTRA_DIST): Add config.rpath, mkinstalldirs, m4/ChangeLog. + * configure.ac (AC_CONFIG_FILES): Add po/Makefile.in. + +2006-09-17 Kenichi Handa + + * configure.ac: Add AM_GNU_GETTEXT. + (GETTEXTDIR): New variable. AC_SUBST it. + +2006-07-19 Kenichi Handa + + * configure.ac: Include the result of `libotf-config --cflags` in + CPPFLAGS. + +2006-07-14 Kenichi Handa + + * configure.ac: Version changed to 1.3.4. Delete args to + AM_INIT_AUTOMAKE. + +2006-06-23 Kenichi Handa + + * Makefile.am (PKGDATA): Don't increment it conditionally. + + * configure.ac: Add "--with-fontconfig" arg. + +2006-05-29 Kenichi Handa + + * m17n-config.in: For for --libtool. + +2006-04-24 TAKAHASHI Naoto + + * README: Insert libthai reference site. + +2006-02-22 Kenichi Handa + + * Version 1.3.3 released. + +2006-02-22 Kenichi Handa + + * configure.ac: Version changed to 1.3.1. + (HAVE_DLOPEN): Fix typo in a message. + +2006-02-06 Kenichi Handa + + * Version 1.3.2 released. + +2006-02-06 Kenichi Handa + + * Makefile.am (EXTRA_DIST): Add bootstrap.sh. + +2006-02-03 Kenichi Handa + + * configure.ac: Version changed to 1.3.1. + +2006-01-17 Kenichi Handa + + * configure.ac: If GD library is available, define HAVE_GD as 1 or + 2 in CONFIG_FLAGS. + +2006-01-16 Kenichi Handa + + * Version 1.3.1 released. + +2006-01-16 Kenichi Handa + + * configure.ac: Version changed to 1.3.1. + +2005-12-22 Kenichi Handa + + * Version 1.3.0 released. + +2005-12-22 Kenichi Handa + + * configure.ac: Check availability of OTF_check_features. + +2005-12-05 Kenichi Handa + + * m17n-shell.pc.in (Description): Fix typo. + +2005-11-21 Kenichi Handa + + * Makefile.am (pkgconfig_DATA): Define it conditionally on + WITH_GUI. + + * configure.ac: Handle --with-gui/--without-gui arg. + +2005-11-18 Kenichi Handa + + * configure.ac: Add --with-libotf option. Use AC_HELP_STRING. + +2005-09-05 Kenichi Handa + + * bootstrap.sh: Call automake with -a -c. + + * configure.ac: Add AM_MAINTAINER_MODE. + (X11_LD_FLAGS): New variable. + (--with-gd): New AC_ARG_WITH. + (HAVE_FRIBIDI_CONFIG): Fix typo for testing it. + +2005-09-01 Kenichi Handa + + * configure.ac (CONFIG_FLAGS): Setup this variable and AC_SUBST it. + +2005-08-18 Kenichi Handa + + * configure.ac: Version changed to 1.3.0. + +2005-05-12 Kenichi Handa + + * configure.ac: Define HAVE_X11_XAW_COMMAND explicitly. + +2005-04-28 Kenichi Handa + + * configure.ac: Check the availability of libXaw. + +2005-04-27 Kenichi Handa + + * configure.ac: Check libthat at first and if that fail check + wordcut library. + +2005-04-15 Kenichi Handa + + * configure.ac: Check the version of wordcut library and + HAVE_WORDCUT or HAVE_WORDCUT_OLD. + (DLOPEN_SHLIB_EXT): Define it. + +2004-12-27 Kenichi Handa + + * Version 1.2.0 released. + +2004-12-27 Kenichi Handa + + * m17n-config.in: Fix documentation. Doxygen's section name fixed. + +2004-12-10 Kenichi Handa + + * configure.ac: Versions changed to 1.2.0. + +2004-10-14 Kenichi Handa + + * configure.ac (M17N_EXT_LIBS): New variable to accumulate + available external libraries. + +2004-10-13 Kenichi Handa + + * configure.ac: Check if is available or not. + +2004-10-12 Kenichi Handa + + * configure.ac: Use pkg-config (if available) for Xft. + +2004-10-11 Kenichi Handa + + * m17n-core.pc.in, m17n-shell.pc.in, m17n-gui.pc.in: New files. + + * configure.ac: Include m17n-core.pc, m17n-shell.pc, and + m17n-gui.pc in AC_CONFIG_FILES. + + * Makefile.am (EXTRA_DIST, pkgconfigdir, pkgconfig_DATA): New + variables. + +2004-08-16 Kenichi Handa + + * Version 1.1.0 released. + +2004-07-06 Kenichi Handa + + * m17n-config.in: Cancel previous change. + +2004-06-30 Kenichi Handa + + * m17n-config.in: Add -lm17n-X and -lm17n-gd if necessary. + +2004-06-14 Kenichi Handa + + * configure.ac: Check the program m17n-db. + +2004-06-03 Kenichi Handa + + * configure.ac: Run freetype-config with --libs instead of + --libtool. + +2004-05-31 Kenichi Handa + + * configure.ac: Check the availability of dlopen. Append + $X_CFLAGS to CPPFLAGS. + +2004-05-28 Kenichi Handa + + * configure.ac: New variable API_VERSION. + + * m17n-config.in: Accept "GUI" flag and adjusted for the new + configuration. + +2004-05-27 Kenichi Handa + + * configure.ac: Check fontconfig even if Xft is available. Check + gd library. If Xft is not available, set XFT2_LD_FLAGS to null. + Likewise for xml2. + + * bootstrap.sh: Clean old files at first. + +2004-05-24 Kenichi Handa + + * configure.ac: Fix typo (pkg-conifg ->pkg-config). Fix + AC_CHECK_LIB arg for fontconfig. + +2004-05-21 Kenichi Handa + + * configure.ac (HAVE_FRIBIDI): Unset FRIBIDI_LD_FLAGS if fribidi + library is not found. + +2004-05-18 Kenichi Handa + + * configure.ac: If libotf is not available, clear OTF_LD_FLAGS. + Double quaote several variables. Even if xft-config is not + available, check if Xft library is available. Setup + HAVE_FONTCONFIG. + +2004-05-07 Kenichi Handa + + * configure.ac: Fix previous change. Comment out xom and effence + related codes. + +2004-05-03 Kenichi Handa + + * configure.ac: Use fribidi-config and xft-config if they are + available. + +2004-04-27 Kenichi Handa + + * configure.ac: Check if Xft2 library is available. + (OTF_LD_FLAGS): Set to `libotf-config --libs`. + (FREETYPE_LD_FLAGS): Set to `freetype-config --libtool`. + +2004-03-29 Kenichi Handa + + * Version 1.0 Patch Level 2 released. + +2004-03-29 Kenichi Handa + + * configure.ac: Version changed to 1.0.2. + +2004-03-19 Kenichi Handa + + * Version 1.0 Patch Level 1 released. + +2004-03-19 Kenichi Handa + + * configure.ac: Version changed to 1.0.1. + +2004-03-01 Kenichi Handa + + * Version 1.0 released. + + +Copyright (C) 2003-2016 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + +This file is part of the m17n library. + +The m17n 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 m17n 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 m17n library; if not, write to the Free +Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..2099840 --- /dev/null +++ b/INSTALL @@ -0,0 +1,370 @@ +Installation Instructions +************************* + +Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, +Inc. + + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. + +Basic Installation +================== + + Briefly, the shell command `./configure && make && make install' +should configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + + The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. + + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + HP-UX `make' updates targets which have the same time stamps as +their prerequisites, which makes it generally unusable when shipped +generated files such as `configure' are involved. Use GNU `make' +instead. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf limitation. Until the limitation is lifted, you can use +this workaround: + + CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..7654b1c --- /dev/null +++ b/Makefile.am @@ -0,0 +1,48 @@ +# Makefile.am -- top level Makefile for the m17n library. +# Copyright (C) 2003-2016 +# National Institute of Advanced Industrial Science and Technology (AIST) +# Registration Number H15PRO112 + +# This file is part of the m17n library. + +# The m17n 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 m17n 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 m17n library; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +## Process this file with Automake to create Makefile.in + +SUBDIRS = intl po src example + +if HAVE_PKG_CONFIG +BINSCRIPTS = +else +BINSCRIPTS = m17n-config +endif +bin_SCRIPTS = $(BINSCRIPTS) + +EXTRA_DIST = \ + m17n-core.pc.in m17n-shell.pc.in m17n-flt.pc.in m17n-gui.pc.in \ + bootstrap.sh + +pkgconfigdir = ${libdir}/pkgconfig + +BASICDATA = m17n-core.pc m17n-shell.pc m17n-flt.pc +if WITH_GUI +PKGDATA = $(BASICDATA) m17n-gui.pc +else +PKGDATA = $(BASICDATA) +endif +pkgconfig_DATA = $(PKGDATA) + +ACLOCAL_AMFLAGS = -I m4 diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..66d0f63 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,1058 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am -- top level Makefile for the m17n library. +# Copyright (C) 2003-2016 +# National Institute of Advanced Industrial Science and Technology (AIST) +# Registration Number H15PRO112 + +# This file is part of the m17n library. + +# The m17n 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 m17n 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 m17n library; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \ + $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \ + $(top_srcdir)/m4/inttypes-pri.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \ + $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \ + $(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = intl/Makefile m17n-config m17n-core.pc \ + m17n-shell.pc m17n-flt.pc m17n-gui.pc +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgconfigdir)" +SCRIPTS = $(bin_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(pkgconfig_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/m17n-config.in $(srcdir)/m17n-core.pc.in \ + $(srcdir)/m17n-flt.pc.in $(srcdir)/m17n-gui.pc.in \ + $(srcdir)/m17n-shell.pc.in $(top_srcdir)/intl/Makefile.in \ + ABOUT-NLS AUTHORS COPYING ChangeLog INSTALL NEWS README TODO \ + compile config.guess config.rpath config.sub install-sh \ + ltmain.sh missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +DIST_TARGETS = dist-gzip +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +ANTHY_CFLAGS = @ANTHY_CFLAGS@ +ANTHY_LD_FLAGS = @ANTHY_LD_FLAGS@ +ANTHY_LIBS = @ANTHY_LIBS@ +API_VERSION = @API_VERSION@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_VISIBILITY = @CFLAG_VISIBILITY@ +CONFIG_FLAGS = @CONFIG_FLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FONTCONFIG_LD_FLAGS = @FONTCONFIG_LD_FLAGS@ +FREETYPE_LD_FLAGS = @FREETYPE_LD_FLAGS@ +FRIBIDI_LD_FLAGS = @FRIBIDI_LD_FLAGS@ +GD_LD_FLAGS = @GD_LD_FLAGS@ +GENCAT = @GENCAT@ +GETTEXTDIR = @GETTEXTDIR@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GLIBC2 = @GLIBC2@ +GLIBC21 = @GLIBC21@ +GLIB_2_0_CFLAGS = @GLIB_2_0_CFLAGS@ +GLIB_2_0_LIBS = @GLIB_2_0_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +HAVE_ASPRINTF = @HAVE_ASPRINTF@ +HAVE_FREETYPE_CONFIG = @HAVE_FREETYPE_CONFIG@ +HAVE_FRIBIDI_CONFIG = @HAVE_FRIBIDI_CONFIG@ +HAVE_ISPELL = @HAVE_ISPELL@ +HAVE_M17N_DB = @HAVE_M17N_DB@ +HAVE_OTFLIB_CONFIG = @HAVE_OTFLIB_CONFIG@ +HAVE_PKG_CONFIG = @HAVE_PKG_CONFIG@ +HAVE_POSIX_PRINTF = @HAVE_POSIX_PRINTF@ +HAVE_SNPRINTF = @HAVE_SNPRINTF@ +HAVE_VISIBILITY = @HAVE_VISIBILITY@ +HAVE_WPRINTF = @HAVE_WPRINTF@ +HAVE_XFT_CONFIG = @HAVE_XFT_CONFIG@ +HAVE_XML2_CONFIG = @HAVE_XML2_CONFIG@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLBISON = @INTLBISON@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBPTH = @LIBPTH@ +LIBPTH_PREFIX = @LIBPTH_PREFIX@ +LIBS = @LIBS@ +LIBTHAI_CFLAGS = @LIBTHAI_CFLAGS@ +LIBTHAI_LIBS = @LIBTHAI_LIBS@ +LIBTHREAD = @LIBTHREAD@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBC = @LTLIBC@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBPTH = @LTLIBPTH@ +LTLIBTHREAD = @LTLIBTHREAD@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +M17NDIR = @M17NDIR@ +M17N_MODULE_DIR = @M17N_MODULE_DIR@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTF_LD_FLAGS = @OTF_LD_FLAGS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSUB = @POSUB@ +POW_LIB = @POW_LIB@ +PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +THAI_WORDSEG_LD_FLAGS = @THAI_WORDSEG_LD_FLAGS@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WINDRES = @WINDRES@ +WOE32 = @WOE32@ +WOE32DLL = @WOE32DLL@ +WORDCUT_CFLAGS = @WORDCUT_CFLAGS@ +WORDCUT_LIBS = @WORDCUT_LIBS@ +X11_LD_FLAGS = @X11_LD_FLAGS@ +XAW_LD_FLAGS = @XAW_LD_FLAGS@ +XFT2_LD_FLAGS = @XFT2_LD_FLAGS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +XMKMF = @XMKMF@ +XML2_LD_FLAGS = @XML2_LD_FLAGS@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = intl po src example +@HAVE_PKG_CONFIG_FALSE@BINSCRIPTS = m17n-config +@HAVE_PKG_CONFIG_TRUE@BINSCRIPTS = +bin_SCRIPTS = $(BINSCRIPTS) +EXTRA_DIST = \ + m17n-core.pc.in m17n-shell.pc.in m17n-flt.pc.in m17n-gui.pc.in \ + bootstrap.sh + +pkgconfigdir = ${libdir}/pkgconfig +BASICDATA = m17n-core.pc m17n-shell.pc m17n-flt.pc +@WITH_GUI_FALSE@PKGDATA = $(BASICDATA) +@WITH_GUI_TRUE@PKGDATA = $(BASICDATA) m17n-gui.pc +pkgconfig_DATA = $(PKGDATA) +ACLOCAL_AMFLAGS = -I m4 +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +intl/Makefile: $(top_builddir)/config.status $(top_srcdir)/intl/Makefile.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +m17n-config: $(top_builddir)/config.status $(srcdir)/m17n-config.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +m17n-core.pc: $(top_builddir)/config.status $(srcdir)/m17n-core.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +m17n-shell.pc: $(top_builddir)/config.status $(srcdir)/m17n-shell.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +m17n-flt.pc: $(top_builddir)/config.status $(srcdir)/m17n-flt.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +m17n-gui.pc: $(top_builddir)/config.status $(srcdir)/m17n-gui.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + --with-included-gettext \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile $(SCRIPTS) $(DATA) config.h +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgconfigdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-pkgconfigDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-binSCRIPTS + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-binSCRIPTS uninstall-pkgconfigDATA + +.MAKE: $(am__recursive_targets) all install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + clean-libtool cscope cscopelist-am ctags ctags-am dist \ + dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ + dist-xz dist-zip distcheck distclean distclean-generic \ + distclean-hdr distclean-libtool distclean-tags distcleancheck \ + distdir distuninstallcheck dvi dvi-am html html-am info \ + info-am install install-am install-binSCRIPTS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-pkgconfigDATA install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-binSCRIPTS \ + uninstall-pkgconfigDATA + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..44630ea --- /dev/null +++ b/NEWS @@ -0,0 +1,271 @@ +* NEWS -- What's new in the m17n library. -*- outline -*- +Copyright (C) 2003-2014 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 +Copyright (C) 2015, 2016, 2017 K. Handa +See the end for copying conditions. + + +* Changes in the m17n library 1.8.0 + +This release is just for bug fixing. + + +* Changes in the m17n library 1.7.1 + +** The command m17n-config is not installed anymore if pkg-config is +available. + + +* Changes in the m17n library 1.7.0 + +** The mechanism of fallback input method is implemented. For that, a +new variable fallback-input-method and new commands switch-im, +push-im, pop-im are supported. + + +* Changes in the m17n library 1.6.4 + +This release is just for bug fixing. + + +* Changes in the m17n library 1.6.3 + +This release is just for bug fixing. + + +* Changes in the m17n library 1.6.2 + +This release is just for bug fixing. + + +* Changes in the m17n library 1.6.1 + +** Libtool 1.5.26 can be used to build the library from CVS source. + + +* Changes in the m17n library 1.6.0 + +** For handling new spec in the Unicode 5.2, these new APIs are added +to m17n-flt.h. + mflt_enable_new_feature + mflt_iterate_otf_feature + mflt_font_id + mflt_try_otf + + +* Changes in the m17n library 1.5.5 + +** Now libtool 2.2.4 or the later is required to build the library +from CVS source. + + +* Changes in the m17n library 1.5.4 + +** New coding system names "Shift_JIS" and "windows-XXXX" are +recognized. + + +* Changes in the m17n library 1.5.3 + +This release is just for bug fixing. + + +* Changes in the m17n library 1.5.2 + +This release is just for bug fixing. + + +* Changes in the m17n library 1.5.1 + +This release is just for bug fixing. + + +* Changes in the m17n library 1.5.0 + +** New API layer FLT is created. + +** New environment variable MDEBUG_FLT is available to turn on +printing debug information for FLT, and these are now obsolete; +MDEBUG_FONT_FLT, MDEBUG_FONT_OTF. + +** New functions mchartable_min_char () returns the mininum character. +that is set some value in a char-table. New funcion +mchartable_min_char () is for the maximum character. + + +* Changes in the m17n library 1.4.0 + +** If the environment variable "M17NDIR" is not set, the directory +"~/.m17n.d" is serched for database files. + +** New function mfont_list_family_names () returns a list of available +font family names. + +** New functions mlanguage_list (), mlanguage_code (), +mlanguage_name_list (), and mlanguage_text () return various +language-related information. + +** New functions mscript_list () and mscript_language_list () return +various script-related information. + +** New function msymbol_put_func (), msymbol_get_func (), +mplist_put_func (), mplist_get_func (), mface_put_hook (), and +mface_get_hook () are available to avoid unsafe casting of function +pointer. New macro M17N_FUNC and new type M17NFunc are also +introduced. + + +* Changes in the m17n library 1.3.0 + +** The `configure' script accepts the argument "--without-gui" to +suppress building GUI libraries. + +** The environment variable MDEBUG_OUTPUT_FILE can specify a file to +output the debugging log messages. + +** The member `candidate_changed' of MInputContext carries more +information; i.e. the list itself is changed, only an index is +changed, etc. + +** The member `callback_list' of MInputDriver can have callback +functions `input-get-surrounding-text' and +`input-delete-surrounding-text'. + +** The minput_filter () function accepts special events +`input-focus-move', `input-focus-in', and `input-focus-out'. + +** Three letter codes of ISO639-2 are also accepted as language +symbols. + +** New functions minput_get_description (), minput_get_commands (), +minput_assign_command_keys (), minput_get_variables (), and +minput_set_variable(), minput_get_title_icon() are introduced for +handling input methods. + +** New fucntions mtext_insert () and and mtext_replace () for +modifying M-text. + +** New functions mtext_uppercase (), mtext_titlecase (), +mtext_lowercase () implement "3.13 Default Case Operations" of The +Unicode Standard 4.0. + +** New function mtext_line_break () implements the line breaking +algorithm of The Unicode Standard 4.0 UAX#14. The algorithm can be +controlled by the variable mdraw_line_break_option. + +** New function msymbol_is_managing_key () checks if a symbol is a +managing key or not. + +** New function mtext_data () exports various information about +M-text. + +** Function mfont_get_prop () accept properties `fontfile', +`font-acsent', `font-descent', and `max-advance'. + +** New function mfont_check () checks if a specific font can be used +for a specific script and language. + +** New function mface_equal () checks if two faces are equal or not. + + +* Changes in the m17n library 1.2.0 + +** Two new variables MTEXT_FORMAT_UTF_16 and MTEXT_FORMAT_UTF_32. +They are initialized to one of MTEXT_FORMAT_UTF_16LE, +MTEXT_FORMAT_UTF_16BE, MTEXT_FORMAT_UTF_LE, MTEXT_FORMAT_UTF_32BE +dependending on the systems's endianess. + +** In the argument PLIST of mframe (), the key Mfont can be used to +specify which font-backend to use. The value must be Mx or Mfreetype. + +** New function mfont_list () returns a list of matching fonts. + +** New function m17n_status () returns the current initialization +status. + +** New function minput_reset () resets the current input context. + +** Names of sample programs have prefix "m17n-" instead of single "m". +This is to avoid confiliction of program names included in the other +packages. + + +* Changes in the m17n library 1.1.0 + +** The "configure" script now detects Fontconfig, Xft2, and GD +libraries. + +If Fontconfig library is found, the library find local font files +(that are to be handled by the Freetype library) by fontconfig, and if +Xft2 library is also found, draw text by Xft. + +** Mdevice (new symbol) is recoginized as a key in the argument PLIST +of mframe (). + +The value must be Mx (new symbol), Mgd (new symbol), or Mnil. See the +documentation of mframe () for more detail. + +** MDrawControl has a new member `anti_alias'. + +If MDrawControl->anti_alias is nonzero, try to draw anti-aliased text +if local fonts are used for that text via Freetype. If Xft2 library +can be used, the anti-alias processing is done by Xft2's drawing +routine. Otherwise, the m17n library itself does it by assumming that +the background color is `background' property of a face. + +** Modification of face is now automatically refelected to the next +drawing. + +So, for instance, an application can change the default face of a +frame after the frame is created. The sample program "medit" utilize +it now. + +** New function mfontset_lookup () reports contents of a fontset. + +** New function mplist_deseriaze () parses an M-Text and generates a +plist. + +** The functions mfont_name () and mfont_from_name () are now obsolete +(still kept for backward compatibility). Use mfont_parse_name () and +mfont_unparse_name () instead. + +** The sample program "mdump" generates PNG image file instead of PBM. + +It now runs only when the m17n library is configured with the Freetype +library and the GD library. + + +* Changes in the m17n library 1.0 + +** Released. + + +* Copyright information + +Copyright (C) 2003-2014 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 +Copyright (C) 2015, 2016, 2017 K. Handa + +This file is part of the m17n library. + +The m17n 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 m17n 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 m17n library; if not, write to the Free +Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. + +Local Variables: +mode: outline +paragraph-separate: "[ ]*$" +End: diff --git a/README b/README new file mode 100644 index 0000000..bea22ef --- /dev/null +++ b/README @@ -0,0 +1,197 @@ +This directory tree holds version 1.8.0 of the m17n library. -*- text -*- + +Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, + 2012, 2013, 2014 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 +Copyright (C) 2015, 2016, 2017 K. Handa +See the end for copying conditions. + +The m17n library is a multilingual text processing library for the C +language. + +----- Table of contents ------ +(1) INSTALLATION +(2) DATABASE +(3) DOCUMENTATION +(4) USAGE +(5) BUGS +------------------------------ + +(1) INSTALLATION + +(1-1) From Git working directory. + +Run the script "bootstrap.sh" in this directory. It is tested that +the script runs successfully with these versions of tools. + + libtool automake autoconf gettext pkg-config + 2.4.2 1.14.1 2.69 0.18.3 0.26 + +(*1) bootstrap.sh prints several warnings something like this: +------------------------------------------------------------ +autoreconf: running: automake --add-missing --copy --force-missing +configure.ac:47: warning: The 'AM_PROG_MKDIR_P' macro is deprecated, and its use is discouraged. +configure.ac:47: You should use the Autoconf-provided 'AC_PROG_MKDIR_P' macro instead, +configure.ac:47: and use '$(MKDIR_P)' instead of '$(mkdir_p)'in your Makefile.am files. +configure.ac:47: installing './config.sub' +configure.ac:28: installing './install-sh' +configure.ac:28: installing './missing' +Makefile.am: installing './INSTALL' +example/Makefile.am:35: warning: 'INCLUDES' is the old name for 'AM_CPPFLAGS' (or '*_CPPFLAGS') +------------------------------------------------------------ +but, it seems that they can be just ignored. + +Then, proceed to the next step. + +(1-2) From the tarball. + +The m17n library utilizes these extra libraries. It is recommended to +install all of them before running the "configure" script. The script +will find out the existence of them automatically. + + libxml2 -- http://xmlsoft.org/ + fribidi -- http://fribidi.sourceforge.net/ + freetype -- http://www.freetype.org/ + libotf -- http://www.m17n.org/libotf/ + fontconfig -- http://freedesktop.org/Software/fontconfig + xft -- http://freedesktop.org/Software/Xft + gd -- http://www.boutell.com/gd/ + +In addition, for finding a word boundary in Thai text, "configure" +checks the existence of these libraries (libthai is preferred): + + libthai -- http://sourceforge.net/projects/libthai + wordcut -- http://thaiwordseg.sourceforge.net/ + +The sample program m17n-edit utilizes this Japanese inputting system. +It is also recommended to install it. + + anthy -- http://anthy.sourceforge.jp/ + +Then, type the followings on the command line. + + % ./configure + % make + % make install + +Note that this package assumes an ANSI C compiler such as gcc. It +will not compile with an old-style K&R compiler. + +The default installation path is "/usr/local". +Thus, these header files are installed in /usr/local/include: + m17n-core.h, m17n.h, m17n-gui.h, m17n-err.h, m17n-X.h, m17n-flt.h + +These library files are installed in /usr/local/lib: + libm17n-core.{a,so*,la} + libm17n.{a,so*,la} + libm17n-gui.{a,so*,la} + libm17n-flt.{a,so*,la} + +These modules are installed in /usr/local/lib/m17n/1.0: + libm17n-X.{a,so*,la} + libm17n-gd.{a,so*,la} + libimx-anthy.{a,so*,la}, + libimx-ispell.{a,so*,la}, + +This shell script is installed in /usr/local/bin: + m17n-config + +These pkgconfig metadata files are installed in +/usr/local/lib/pkgconfig: + m17n-core.pc, m17n-shell.pc, m17n-flt.pc, m17n-gui.pc + +These sample programs are installed in /usr/local/bin too: + m17n-conv, m17n-date, m17n-view, m17n-dump, m17n-edit + +If you don't need GUI libraries (libm17n-gui.so and etc.), you can +instruct the `configure' script not to build them as below: + + % ./configure --without-gui + +This file under `example' sub-directory is a Japanese resource file +for m17n-edit. It is not installed but useful in Japanese locale. Copy +it to your home directory (or, for instance, +/usr/X11R6/lib/X11/ja/app-defaults) and rename it to "M17NEdit" if you +want to see labels in Japanese: + M17NEdit.ja + +These text files under `example' sub-directory are not installed but +useful for testing the rendering engine of the m17n library: + HELLO.utf8 HELLO.xml HELLO-ja.utf8 HELLO-ja.xml HELLO.html +XXX.xml are generated from XXX.utf8 by attaching text property +`language' and serializing. + +Please read also INSTALL for the generic installation instructions. + + +(2) DATABASE + +The m17n library utilizes the m17n database available at: + http://www.m17n.org/m17n-lib/m17n-db +Without this database, the m17n library loses half its value. Please +install it (Ver.1.4.0 or the later is required) too before you try the +above sample programs or develop a program that uses the m17n library. + + +(3) DOCUMENTATION + +This page has a link to full documentation of the m17n library: + http://www.m17n.org/m17n-lib + +Actually, the documentation was generated by Doxygen using comments in +the source files. There are English and Japanese comments in +parallel. + + +(4) USAGE + +The library provides three levels of APIs, CORE, SHELL, and GUI. For +CORE API, include , for SHELL API, include , and +for GUI API, include . In addition, for those who need +only text shaping facility that uses FLT (Font Layout Table), the +library provides FLT API. To use it, include . + +See the documentation above, or the manual of m17nIntro(3) for more +detail. + +The shell script "m17n-config" helps compiling and linking of a +program that uses the m17n library. For instance this compiles PROG.c +that uses SHELL API and builds executable PROG. + + % gcc -o PROG `m17n-config --cflags` `m17n-config --libs` PROG.c + +This compiles PROX.c that uses GUI API and builds executable PROX. + + % gcc -o PROX `m17n-config GUI --cflags` `m17n-config GUI --libs` PROX.c + + +(5) BUGS + +Please email bug reports to m17n-list@nongnu.org. + +---------------------------------------------------------------------- +Copyright information + +Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, + 2012, 2013, 2014 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 +Copyright (C) 2015, 2016, 2017 K. Handa + +This file is part of the m17n library. + +The m17n 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 m17n 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 m17n library; if not, write to the Free +Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. diff --git a/TODO b/TODO new file mode 100644 index 0000000..cf8eb85 --- /dev/null +++ b/TODO @@ -0,0 +1,60 @@ +TODO -- todo list for the m17n library. -*- outline -*- +Copyright (C) 2003, 2004 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 +See the end for copying conditions. + + +* soon + +** Explicitely list up managed objects and describe them. + +** Allow properties to M-text itself, not to a specific region. + + +* later + +** Add in MFont to allow any property. + +** Allow regex for font properties. + +** Should we change the type of property value from (void *) to +MPropValue? + +** Vietnames FLT needs compositions. + +** Lock and unlock M-text. + +** Improve the handling of scratch gstring. + + +* done + +** Make such an M-text modifiable that has a format other than +MTEXT_FORMAT_UTF_8. + +** Imporve the font selection for characters of the same script. + + +* Copyright information + +Copyright (C) 2003, 2004 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + +This file is part of the m17n library. + +The m17n 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 m17n 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 m17n library; if not, write to the Free +Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..b7aa71f --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,1529 @@ +# generated automatically by aclocal 1.15 -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. + +# 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29.1) +dnl +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.1]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +# Copyright (C) 2002-2014 Free Software Foundation, Inc. +# +# 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. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.15' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.15], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.15])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# 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. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# +# 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. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# 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. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# 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. + + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each '.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# 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. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# 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. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2014 Free Software Foundation, Inc. +# +# 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. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# 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. + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless 'enable' is passed literally. +# For symmetry, 'disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], + [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], + am_maintainer_other[ make rules and dependencies not useful + (and sometimes confusing) to the casual installer])], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# 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. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# +# 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. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003-2014 Free Software Foundation, Inc. +# +# 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. + +# AM_PROG_MKDIR_P +# --------------- +# Check for 'mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl FIXME we are no longer going to remove this! adjust warning +dnl FIXME message accordingly. +AC_DIAGNOSE([obsolete], +[$0: this macro is deprecated, and will soon be removed. +You should use the Autoconf-provided 'AC][_PROG_MKDIR_P' macro instead, +and use '$(MKDIR_P)' instead of '$(mkdir_p)'in your Makefile.am files.]) +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# 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. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# 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. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# 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. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# 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. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2014 Free Software Foundation, Inc. +# +# 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. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# 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. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2014 Free Software Foundation, Inc. +# +# 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. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2014 Free Software Foundation, Inc. +# +# 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. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([m4/codeset.m4]) +m4_include([m4/gettext.m4]) +m4_include([m4/glibc2.m4]) +m4_include([m4/glibc21.m4]) +m4_include([m4/iconv.m4]) +m4_include([m4/intdiv0.m4]) +m4_include([m4/intl.m4]) +m4_include([m4/intlmacosx.m4]) +m4_include([m4/intmax.m4]) +m4_include([m4/inttypes-pri.m4]) +m4_include([m4/inttypes_h.m4]) +m4_include([m4/lcmessage.m4]) +m4_include([m4/lib-ld.m4]) +m4_include([m4/lib-link.m4]) +m4_include([m4/lib-prefix.m4]) +m4_include([m4/libtool.m4]) +m4_include([m4/lock.m4]) +m4_include([m4/longlong.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) +m4_include([m4/nls.m4]) +m4_include([m4/po.m4]) +m4_include([m4/printf-posix.m4]) +m4_include([m4/progtest.m4]) +m4_include([m4/size_max.m4]) +m4_include([m4/stdint_h.m4]) +m4_include([m4/uintmax_t.m4]) +m4_include([m4/visibility.m4]) +m4_include([m4/wchar_t.m4]) +m4_include([m4/wint_t.m4]) +m4_include([m4/xsize.m4]) diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 0000000..1b5cfc8 --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# bootstrap.sh -- shell script to build the m17n library from CVS. +# Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010, 2011, 2012 +# National Institute of Advanced Industrial Science and Technology (AIST) +# Registration Number H15PRO112 + +# This file is part of the m17n library. + +# The m17n 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 m17n 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 m17n library; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +echo "Cleaning up old files..." +rm -rf INSTALL aclocal.m4 autom4te.cache config.guess. config.rpath config.sub install-sh libtool ltmain.sh missing mkinstalldirs intl/[D-Za-z]* m4/[a-z]* + +echo "Running autoreconf -v -f -i" +autoreconf -v -f -i +if [ ! -f po/Makevars ] ; then + echo "Copying po/Makevars.template to po/Makevars" + cp po/Makevars.template po/Makevars +fi +echo "The remaining steps to install this library are:" +echo " % ./configure" +echo " % make" +echo " % make install" diff --git a/compile b/compile new file mode 100755 index 0000000..a85b723 --- /dev/null +++ b/compile @@ -0,0 +1,347 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2012-10-14.11; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# 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, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/config.guess b/config.guess new file mode 100755 index 0000000..1659250 --- /dev/null +++ b/config.guess @@ -0,0 +1,1441 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2015 Free Software Foundation, Inc. + +timestamp='2015-08-20' + +# This file 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 3 of the License, 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, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || \ + echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown + ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case "${UNAME_MACHINE_ARCH}" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}${abi}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:Sortix:*:*) + echo ${UNAME_MACHINE}-unknown-sortix + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + e2k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..27d2915 --- /dev/null +++ b/config.h.in @@ -0,0 +1,547 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +#undef CRAY_STACKSEG_END + +/* Define to 1 if using `alloca.c'. */ +#undef C_ALLOCA + +/* Define to loadable module extention */ +#undef DLOPEN_SHLIB_EXT + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +#undef ENABLE_NLS + +/* Define to 1 if you have `alloca', as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#undef HAVE_ALLOCA_H + +/* Define to 1 if you have Anthy library and header file */ +#undef HAVE_ANTHY + +/* Define to 1 if you have the `argz_count' function. */ +#undef HAVE_ARGZ_COUNT + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARGZ_H + +/* Define to 1 if you have the `argz_next' function. */ +#undef HAVE_ARGZ_NEXT + +/* Define to 1 if you have the `argz_stringify' function. */ +#undef HAVE_ARGZ_STRINGIFY + +/* Define to 1 if you have the `asprintf' function. */ +#undef HAVE_ASPRINTF + +/* Define to 1 if the compiler understands __builtin_expect. */ +#undef HAVE_BUILTIN_EXPECT + +/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the + CoreFoundation framework. */ +#undef HAVE_CFLOCALECOPYCURRENT + +/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in + the CoreFoundation framework. */ +#undef HAVE_CFPREFERENCESCOPYAPPVALUE + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +#undef HAVE_DCGETTEXT + +/* Define to 1 if you have the declaration of `feof_unlocked', and to 0 if you + don't. */ +#undef HAVE_DECL_FEOF_UNLOCKED + +/* Define to 1 if you have the declaration of `fgets_unlocked', and to 0 if + you don't. */ +#undef HAVE_DECL_FGETS_UNLOCKED + +/* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you + don't. */ +#undef HAVE_DECL_GETC_UNLOCKED + +/* Define to 1 if you have the declaration of `_snprintf', and to 0 if you + don't. */ +#undef HAVE_DECL__SNPRINTF + +/* Define to 1 if you have the declaration of `_snwprintf', and to 0 if you + don't. */ +#undef HAVE_DECL__SNWPRINTF + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the function dlopen. */ +#undef HAVE_DLOPEN + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have fontconfig library and header file. */ +#undef HAVE_FONTCONFIG + +/* Define to 1 if you have FreeType library and header file. */ +#undef HAVE_FREETYPE + +/* Define to 1 if you have Fribidi library and header file. */ +#undef HAVE_FRIBIDI + +/* Define to 1 if you have freetype/ftbdf.h. */ +#undef HAVE_FTBDF_H + +/* Define to 1 if you have the `fwprintf' function. */ +#undef HAVE_FWPRINTF + +/* Define to 1 or 2 if you have gd library and header file. */ +#undef HAVE_GD + +/* Define to 1 if you have the `getcwd' function. */ +#undef HAVE_GETCWD + +/* Define to 1 if you have the `getegid' function. */ +#undef HAVE_GETEGID + +/* Define to 1 if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define to 1 if you have the `getgid' function. */ +#undef HAVE_GETGID + +/* Define to 1 if you have the `getpagesize' function. */ +#undef HAVE_GETPAGESIZE + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#undef HAVE_GETTEXT + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `getuid' function. */ +#undef HAVE_GETUID + +/* Define if you have the iconv() function and it works. */ +#undef HAVE_ICONV + +/* Define if you have the 'intmax_t' type in or . */ +#undef HAVE_INTMAX_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define if exists, doesn't clash with , and + declares uintmax_t. */ +#undef HAVE_INTTYPES_H_WITH_UINTMAX + +/* Define if ispell is available. */ +#undef HAVE_ISPELL + +/* Define if you have and nl_langinfo(CODESET). */ +#undef HAVE_LANGINFO_CODESET + +/* Define to 1 if you have the header file. */ +#undef HAVE_LANGINFO_H + +/* Define if your file defines LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES + +/* Define if you have libthai */ +#undef HAVE_LIBTHAI + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define to 1 if the system has the type `long long int'. */ +#undef HAVE_LONG_LONG_INT + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the `memmove' function. */ +#undef HAVE_MEMMOVE + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `mempcpy' function. */ +#undef HAVE_MEMPCPY + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define to 1 if you have the `munmap' function. */ +#undef HAVE_MUNMAP + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the `nl_langinfo' function. */ +#undef HAVE_NL_LANGINFO + +/* Define if you have and it defines the NL_LOCALE_NAME macro if + _GNU_SOURCE is defined. */ +#undef HAVE_NL_LOCALE_NAME + +/* Define to 1 if you have OTF library and header file. */ +#undef HAVE_OTF + +/* Define to 1 if the OTF library has OTF_drive_gpos2(). */ +#undef HAVE_OTF_DRIVE_GPOS2 + +/* Define if your printf() function supports format strings with positions. */ +#undef HAVE_POSIX_PRINTF + +/* Define if the defines PTHREAD_MUTEX_RECURSIVE. */ +#undef HAVE_PTHREAD_MUTEX_RECURSIVE + +/* Define if the POSIX multithreading library has read/write locks. */ +#undef HAVE_PTHREAD_RWLOCK + +/* Define to 1 if you have the `putenv' function. */ +#undef HAVE_PUTENV + +/* Define to 1 if your system has a GNU libc compatible `realloc' function, + and to 0 otherwise. */ +#undef HAVE_REALLOC + +/* Define to 1 if you have the `regcomp' function. */ +#undef HAVE_REGCOMP + +/* Define to 1 if you have the `setenv' function. */ +#undef HAVE_SETENV + +/* Define to 1 if you have the `setlocale' function. */ +#undef HAVE_SETLOCALE + +/* Define to 1 if you have the `snprintf' function. */ +#undef HAVE_SNPRINTF + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +#undef HAVE_STAT_EMPTY_STRING_BUG + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define if exists, doesn't clash with , and declares + uintmax_t. */ +#undef HAVE_STDINT_H_WITH_UINTMAX + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `stpcpy' function. */ +#undef HAVE_STPCPY + +/* Define to 1 if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strcoll' function and it is properly defined. + */ +#undef HAVE_STRCOLL + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the `strftime' function. */ +#undef HAVE_STRFTIME + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strtoul' function. */ +#undef HAVE_STRTOUL + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define if you have some Thai word-segmentation library */ +#undef HAVE_THAI_WORDSEG + +/* Define to 1 if you have the `tsearch' function. */ +#undef HAVE_TSEARCH + +/* Define if you have the 'uintmax_t' type in or . */ +#undef HAVE_UINTMAX_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if the system has the type `unsigned long long int'. */ +#undef HAVE_UNSIGNED_LONG_LONG_INT + +/* Define to 1 or 0, depending whether the compiler supports simple visibility + declarations. */ +#undef HAVE_VISIBILITY + +/* Define if you have the 'wchar_t' type. */ +#undef HAVE_WCHAR_T + +/* Define to 1 if you have the `wcslen' function. */ +#undef HAVE_WCSLEN + +/* Define if you have the 'wint_t' type. */ +#undef HAVE_WINT_T + +/* Define if you have the wordcut library and header file */ +#undef HAVE_WORDCUT + +/* Define if you have the old version of wordcut library */ +#undef HAVE_WORDCUT_OLD + +/* Define to 1 if you have X11. */ +#undef HAVE_X11 + +/* Define to 1 if you have the Xaw header files. */ +#undef HAVE_X11_XAW_COMMAND_H + +/* Define to 1 if you have Xft2 library and header file. */ +#undef HAVE_XFT2 + +/* Define to 1 if you have libxml2 library and header file */ +#undef HAVE_XML2 + +/* Define to 1 if you have the `__fsetlocking' function. */ +#undef HAVE___FSETLOCKING + +/* Define as const if the declaration of iconv() needs const. */ +#undef ICONV_CONST + +/* Define if integer division by zero raises signal SIGFPE. */ +#undef INTDIV0_RAISES_SIGFPE + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +#undef LSTAT_FOLLOWS_SLASHED_SYMLINK + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define if exists and defines unusable PRI* macros. */ +#undef PRI_MACROS_BROKEN + +/* Define if the pthread_in_use() detection is hard. */ +#undef PTHREAD_IN_USE_DETECTION_HARD + +/* Define as the maximum value of type 'size_t', if the system doesn't define + it. */ +#undef SIZE_MAX + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +#undef STACK_DIRECTION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Define if the POSIX multithreading library can be used. */ +#undef USE_POSIX_THREADS + +/* Define if references to the POSIX multithreading library should be made + weak. */ +#undef USE_POSIX_THREADS_WEAK + +/* Define if the GNU Pth multithreading library can be used. */ +#undef USE_PTH_THREADS + +/* Define if references to the GNU Pth multithreading library should be made + weak. */ +#undef USE_PTH_THREADS_WEAK + +/* Define if the old Solaris multithreading library can be used. */ +#undef USE_SOLARIS_THREADS + +/* Define if references to the old Solaris multithreading library should be + made weak. */ +#undef USE_SOLARIS_THREADS_WEAK + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + +/* Define if the Win32 multithreading API can be used. */ +#undef USE_WIN32_THREADS + +/* Version number of package */ +#undef VERSION + +/* Define tdict file name */ +#undef WORDCUT_TDICT + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif + +/* Define to 1 if the X Window System is missing or not being used. */ +#undef X_DISPLAY_MISSING + +/* Define to 1 if on MINIX. */ +#undef _MINIX + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to rpl_malloc if the replacement function should be used. */ +#undef malloc + +/* Define as the type of the result of subtracting two pointers, if the system + doesn't define it. */ +#undef ptrdiff_t + +/* Define to rpl_realloc if the replacement function should be used. */ +#undef realloc + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to unsigned long or unsigned long long if and + don't define. */ +#undef uintmax_t + + +#define __libc_lock_t gl_lock_t +#define __libc_lock_define gl_lock_define +#define __libc_lock_define_initialized gl_lock_define_initialized +#define __libc_lock_init gl_lock_init +#define __libc_lock_lock gl_lock_lock +#define __libc_lock_unlock gl_lock_unlock +#define __libc_lock_recursive_t gl_recursive_lock_t +#define __libc_lock_define_recursive gl_recursive_lock_define +#define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized +#define __libc_lock_init_recursive gl_recursive_lock_init +#define __libc_lock_lock_recursive gl_recursive_lock_lock +#define __libc_lock_unlock_recursive gl_recursive_lock_unlock +#define glthread_in_use libintl_thread_in_use +#define glthread_lock_init libintl_lock_init +#define glthread_lock_lock libintl_lock_lock +#define glthread_lock_unlock libintl_lock_unlock +#define glthread_lock_destroy libintl_lock_destroy +#define glthread_rwlock_init libintl_rwlock_init +#define glthread_rwlock_rdlock libintl_rwlock_rdlock +#define glthread_rwlock_wrlock libintl_rwlock_wrlock +#define glthread_rwlock_unlock libintl_rwlock_unlock +#define glthread_rwlock_destroy libintl_rwlock_destroy +#define glthread_recursive_lock_init libintl_recursive_lock_init +#define glthread_recursive_lock_lock libintl_recursive_lock_lock +#define glthread_recursive_lock_unlock libintl_recursive_lock_unlock +#define glthread_recursive_lock_destroy libintl_recursive_lock_destroy +#define glthread_once libintl_once +#define glthread_once_call libintl_once_call +#define glthread_once_singlethreaded libintl_once_singlethreaded + diff --git a/config.rpath b/config.rpath new file mode 100755 index 0000000..c547c68 --- /dev/null +++ b/config.rpath @@ -0,0 +1,666 @@ +#! /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-2007 Free Software Foundation, Inc. +# Taken from GNU libtool, 2001 +# Originally by Gordon Matzigkeit , 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 AC_LIBTOOL_PROG_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*) + ;; + hpux9* | hpux10* | hpux11*) + wl='-Wl,' + ;; + irix5* | irix6* | nonstopux*) + wl='-Wl,' + ;; + newsos6) + ;; + linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + 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 AC_LIBTOOL_PROG_LD_SHLIBS. + +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no + +case "$host_os" in + cygwin* | mingw* | pw32*) + # 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 + aix3* | aix4* | aix5*) + # 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 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*) + # 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 + ;; + aix4* | aix5*) + 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].*|aix5*) + 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*) + # 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 AC_LIBTOOL_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' + ;; + aix4* | aix5*) + 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*) + 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=/' <. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2015 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | e2k-* | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + asmjs) + basic_machine=asmjs-unknown + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 0000000..6bb538a --- /dev/null +++ b/configure @@ -0,0 +1,23596 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for m17n-lib 1.8.0. +# +# Report bugs to . +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: m17n-lib-bug@m17n.org about your system, including any +$0: error possibly output before this message. Then install +$0: a modern shell, or manually run the script under such a +$0: shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='m17n-lib' +PACKAGE_TARNAME='m17n-lib' +PACKAGE_VERSION='1.8.0' +PACKAGE_STRING='m17n-lib 1.8.0' +PACKAGE_BUGREPORT='m17n-lib-bug@m17n.org' +PACKAGE_URL='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +gt_needs= +ac_header_list= +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +CONFIG_FLAGS +THAI_WORDSEG_LD_FLAGS +GLIB_2_0_LIBS +GLIB_2_0_CFLAGS +WORDCUT_LIBS +WORDCUT_CFLAGS +LIBTHAI_LIBS +LIBTHAI_CFLAGS +HAVE_ISPELL +ANTHY_LD_FLAGS +ANTHY_LIBS +ANTHY_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +XML2_LD_FLAGS +HAVE_XML2_CONFIG +GD_LD_FLAGS +FONTCONFIG_LD_FLAGS +XFT2_LD_FLAGS +HAVE_XFT_CONFIG +FREETYPE_LD_FLAGS +HAVE_FREETYPE_CONFIG +OTF_LD_FLAGS +HAVE_OTFLIB_CONFIG +FRIBIDI_LD_FLAGS +HAVE_FRIBIDI_CONFIG +XAW_LD_FLAGS +X11_LD_FLAGS +HAVE_PKG_CONFIG_FALSE +HAVE_PKG_CONFIG_TRUE +HAVE_PKG_CONFIG +WITH_GUI_FALSE +WITH_GUI_TRUE +M17NDIR +HAVE_M17N_DB +POW_LIB +LIBOBJS +X_EXTRA_LIBS +X_LIBS +X_PRE_LIBS +X_CFLAGS +XMKMF +LT_SYS_LIBRARY_PATH +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +ac_ct_AR +AR +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +SED +LIBTOOL +GETTEXTDIR +POSUB +LTLIBINTL +LIBINTL +INTLLIBS +INTL_LIBTOOL_SUFFIX_PREFIX +INTLOBJS +GENCAT +INSTOBJEXT +DATADIRNAME +CATOBJEXT +USE_INCLUDED_LIBINTL +BUILD_INCLUDED_LIBINTL +LTLIBC +WINDRES +WOE32 +WOE32DLL +HAVE_WPRINTF +HAVE_SNPRINTF +HAVE_ASPRINTF +HAVE_POSIX_PRINTF +INTL_MACOSX_LIBS +GLIBC21 +INTLBISON +LTLIBICONV +LIBICONV +LTLIBMULTITHREAD +LIBMULTITHREAD +LTLIBTHREAD +LIBTHREAD +LIBPTH_PREFIX +LTLIBPTH +LIBPTH +PRI_MACROS_BROKEN +ALLOCA +HAVE_VISIBILITY +CFLAG_VISIBILITY +RANLIB +GLIBC2 +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +XGETTEXT_EXTRA_OPTIONS +MSGMERGE +XGETTEXT_015 +XGETTEXT +GMSGFMT_015 +MSGFMT_015 +GMSGFMT +MSGFMT +GETTEXT_MACRO_VERSION +USE_NLS +EGREP +GREP +CPP +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +M17N_MODULE_DIR +API_VERSION +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +runstatedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_maintainer_mode +enable_dependency_tracking +enable_nls +enable_threads +with_gnu_ld +enable_rpath +with_libpth_prefix +with_libiconv_prefix +with_included_gettext +with_libintl_prefix +enable_shared +enable_static +with_pic +enable_fast_install +with_aix_soname +with_sysroot +enable_libtool_lock +with_x +enable_gui +with_libotf +with_fontconfig +with_gd +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +LT_SYS_LIBRARY_PATH +XMKMF +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +ANTHY_CFLAGS +ANTHY_LIBS +LIBTHAI_CFLAGS +LIBTHAI_LIBS +WORDCUT_CFLAGS +WORDCUT_LIBS +GLIB_2_0_CFLAGS +GLIB_2_0_LIBS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir runstatedir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures m17n-lib 1.8.0 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/m17n-lib] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of m17n-lib 1.8.0:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-maintainer-mode + enable make rules and dependencies not useful (and + sometimes confusing) to the casual installer + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --disable-nls do not use Native Language Support + --enable-threads={posix|solaris|pth|win32} + specify multithreading API + --disable-threads build without multithread safety + --disable-rpath do not hardcode runtime library paths + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --enable-gui enable GUI level APIs (default is YES) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-gnu-ld assume the C compiler uses GNU ld default=no + --with-libpth-prefix[=DIR] search for libpth in DIR/include and DIR/lib + --without-libpth-prefix don't search for libpth in includedir and libdir + --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib + --without-libiconv-prefix don't search for libiconv in includedir and libdir + --with-included-gettext use the GNU gettext library included here + --with-libintl-prefix[=DIR] search for libintl in DIR/include and DIR/lib + --without-libintl-prefix don't search for libintl in includedir and libdir + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use + both] + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). + --with-x use the X Window System + --with-libotf with OpenType font suport (default is YES) + --with-fontconfig with FontConfig library (default is YES) + --with-gd suport graphic device by GD library (default is YES) + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. + XMKMF Path to xmkmf, Makefile generator for X Window System + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + ANTHY_CFLAGS + C compiler flags for ANTHY, overriding pkg-config + ANTHY_LIBS linker flags for ANTHY, overriding pkg-config + LIBTHAI_CFLAGS + C compiler flags for LIBTHAI, overriding pkg-config + LIBTHAI_LIBS + linker flags for LIBTHAI, overriding pkg-config + WORDCUT_CFLAGS + C compiler flags for WORDCUT, overriding pkg-config + WORDCUT_LIBS + linker flags for WORDCUT, overriding pkg-config + GLIB_2_0_CFLAGS + C compiler flags for GLIB_2_0, overriding pkg-config + GLIB_2_0_LIBS + linker flags for GLIB_2_0, overriding pkg-config + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +m17n-lib configure 1.8.0 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ------------------------------------ ## +## Report this to m17n-lib-bug@m17n.org ## +## ------------------------------------ ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES +# -------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_c_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid; break +else + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=$ac_mid; break +else + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid +else + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + echo >>conftest.val; read $3 config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by m17n-lib $as_me 1.8.0, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +gt_needs="$gt_needs " +as_fn_append ac_header_list " stdlib.h" +as_fn_append ac_header_list " unistd.h" +as_fn_append ac_header_list " sys/param.h" +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +am__api_version='1.15' + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='m17n-lib' + VERSION='1.8.0' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar pax cpio none' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + +ac_config_headers="$ac_config_headers config.h" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + + +API_VERSION=4:2:4 + + +# The earliest version that this release has binary compatibility +# with. This is used for module locations. +M17N_BINARY_VERSION=1.0 + +M17N_MODULE_DIR="m17n/$M17N_BINARY_VERSION" + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = xyes; then : + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h + + +$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h + + +$as_echo "#define _MINIX 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if ${ac_cv_safe_to_define___extensions__+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes +else + ac_cv_safe_to_define___extensions__=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h + + $as_echo "#define _ALL_SOURCE 1" >>confdefs.h + + $as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h + + + + + +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 +$as_echo_n "checking whether NLS is requested... " >&6; } + # Check whether --enable-nls was given. +if test "${enable_nls+set}" = set; then : + enableval=$enable_nls; USE_NLS=$enableval +else + USE_NLS=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +$as_echo "$USE_NLS" >&6; } + + + + + GETTEXT_MACRO_VERSION=0.17 + + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$MSGFMT" in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --statistics /dev/null >&5 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + ac_cv_path_MSGFMT="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test "$MSGFMT" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 +$as_echo "$MSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GMSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GMSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT=$ac_cv_path_GMSGFMT +if test -n "$GMSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 +$as_echo "$GMSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac + + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_XGETTEXT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$XGETTEXT" in + [\\/]* | ?:[\\/]*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&5 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test "$XGETTEXT" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 +$as_echo "$XGETTEXT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + rm -f messages.po + + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "msgmerge", so it can be a program name with args. +set dummy msgmerge; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGMERGE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$MSGMERGE" in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --update -q /dev/null /dev/null >&5 2>&1; then + ac_cv_path_MSGMERGE="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_MSGMERGE" && ac_cv_path_MSGMERGE=":" + ;; +esac +fi +MSGMERGE="$ac_cv_path_MSGMERGE" +if test "$MSGMERGE" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 +$as_echo "$MSGMERGE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$localedir" || localedir='${datadir}/locale' + + + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + + + ac_config_commands="$ac_config_commands po-directories" + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C Library 2 or newer" >&5 +$as_echo_n "checking whether we are using the GNU C Library 2 or newer... " >&6; } +if ${ac_cv_gnu_library_2+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ >= 2) + Lucky GNU user + #endif +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "Lucky GNU user" >/dev/null 2>&1; then : + ac_cv_gnu_library_2=yes +else + ac_cv_gnu_library_2=no +fi +rm -f conftest* + + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_gnu_library_2" >&5 +$as_echo "$ac_cv_gnu_library_2" >&6; } + + GLIBC2="$ac_cv_gnu_library_2" + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + + + + CFLAG_VISIBILITY= + HAVE_VISIBILITY=0 + if test -n "$GCC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for simple visibility declarations" >&5 +$as_echo_n "checking for simple visibility declarations... " >&6; } + if ${gl_cv_cc_visibility+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fvisibility=hidden" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +extern __attribute__((__visibility__("hidden"))) int hiddenvar; + extern __attribute__((__visibility__("default"))) int exportedvar; + extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void); + extern __attribute__((__visibility__("default"))) int exportedfunc (void); +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gl_cv_cc_visibility=yes +else + gl_cv_cc_visibility=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$gl_save_CFLAGS" +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_cc_visibility" >&5 +$as_echo "$gl_cv_cc_visibility" >&6; } + if test $gl_cv_cc_visibility = yes; then + CFLAG_VISIBILITY="-fvisibility=hidden" + HAVE_VISIBILITY=1 + fi + fi + + + +cat >>confdefs.h <<_ACEOF +#define HAVE_VISIBILITY $HAVE_VISIBILITY +_ACEOF + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint.h" >&5 +$as_echo_n "checking for stdint.h... " >&6; } +if ${gl_cv_header_stdint_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +int +main () +{ +uintmax_t i = (uintmax_t) -1; return !i; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gl_cv_header_stdint_h=yes +else + gl_cv_header_stdint_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_header_stdint_h" >&5 +$as_echo "$gl_cv_header_stdint_h" >&6; } + if test $gl_cv_header_stdint_h = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STDINT_H_WITH_UINTMAX 1 +_ACEOF + + fi + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5 +$as_echo_n "checking for working alloca.h... " >&6; } +if ${ac_cv_working_alloca_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +char *p = (char *) alloca (2 * sizeof (int)); + if (p) return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_working_alloca_h=yes +else + ac_cv_working_alloca_h=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5 +$as_echo "$ac_cv_working_alloca_h" >&6; } +if test $ac_cv_working_alloca_h = yes; then + +$as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5 +$as_echo_n "checking for alloca... " >&6; } +if ${ac_cv_func_alloca_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# ifdef HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +void *alloca (size_t); +# endif +# endif +# endif +# endif +#endif + +int +main () +{ +char *p = (char *) alloca (1); + if (p) return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_func_alloca_works=yes +else + ac_cv_func_alloca_works=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5 +$as_echo "$ac_cv_func_alloca_works" >&6; } + +if test $ac_cv_func_alloca_works = yes; then + +$as_echo "#define HAVE_ALLOCA 1" >>confdefs.h + +else + # The SVR3 libPW and SVR4 libucb both contain incompatible functions +# that cause trouble. Some versions do not even contain alloca or +# contain a buggy version. If you still want to use their alloca, +# use ar to extract alloca.o from them instead of compiling alloca.c. + +ALLOCA=\${LIBOBJDIR}alloca.$ac_objext + +$as_echo "#define C_ALLOCA 1" >>confdefs.h + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5 +$as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; } +if ${ac_cv_os_cray+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined CRAY && ! defined CRAY2 +webecray +#else +wenotbecray +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "webecray" >/dev/null 2>&1; then : + ac_cv_os_cray=yes +else + ac_cv_os_cray=no +fi +rm -f conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5 +$as_echo "$ac_cv_os_cray" >&6; } +if test $ac_cv_os_cray = yes; then + for ac_func in _getb67 GETB67 getb67; do + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + +cat >>confdefs.h <<_ACEOF +#define CRAY_STACKSEG_END $ac_func +_ACEOF + + break +fi + + done +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5 +$as_echo_n "checking stack direction for C alloca... " >&6; } +if ${ac_cv_c_stack_direction+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_c_stack_direction=0 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +find_stack_direction (int *addr, int depth) +{ + int dir, dummy = 0; + if (! addr) + addr = &dummy; + *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1; + dir = depth ? find_stack_direction (addr, depth - 1) : 0; + return dir + dummy; +} + +int +main (int argc, char **argv) +{ + return find_stack_direction (0, argc + !argv + 20) < 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_stack_direction=1 +else + ac_cv_c_stack_direction=-1 +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5 +$as_echo "$ac_cv_c_stack_direction" >&6; } +cat >>confdefs.h <<_ACEOF +#define STACK_DIRECTION $ac_cv_c_stack_direction +_ACEOF + + +fi + + + + + for ac_header in $ac_header_list +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + + +for ac_func in getpagesize +do : + ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize" +if test "x$ac_cv_func_getpagesize" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETPAGESIZE 1 +_ACEOF + +fi +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working mmap" >&5 +$as_echo_n "checking for working mmap... " >&6; } +if ${ac_cv_func_mmap_fixed_mapped+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_mmap_fixed_mapped=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +/* malloc might have been renamed as rpl_malloc. */ +#undef malloc + +/* Thanks to Mike Haertel and Jim Avera for this test. + Here is a matrix of mmap possibilities: + mmap private not fixed + mmap private fixed at somewhere currently unmapped + mmap private fixed at somewhere already mapped + mmap shared not fixed + mmap shared fixed at somewhere currently unmapped + mmap shared fixed at somewhere already mapped + For private mappings, we should verify that changes cannot be read() + back from the file, nor mmap's back from the file at a different + address. (There have been systems where private was not correctly + implemented like the infamous i386 svr4.0, and systems where the + VM page cache was not coherent with the file system buffer cache + like early versions of FreeBSD and possibly contemporary NetBSD.) + For shared mappings, we should conversely verify that changes get + propagated back to all the places they're supposed to be. + + Grep wants private fixed already mapped. + The main things grep needs to know about mmap are: + * does it exist and is it safe to write into the mmap'd area + * how to use it (BSD variants) */ + +#include +#include + +#if !defined STDC_HEADERS && !defined HAVE_STDLIB_H +char *malloc (); +#endif + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +int +main () +{ + char *data, *data2, *data3; + const char *cdata2; + int i, pagesize; + int fd, fd2; + + pagesize = getpagesize (); + + /* First, make a file with some known garbage in it. */ + data = (char *) malloc (pagesize); + if (!data) + return 1; + for (i = 0; i < pagesize; ++i) + *(data + i) = rand (); + umask (0); + fd = creat ("conftest.mmap", 0600); + if (fd < 0) + return 2; + if (write (fd, data, pagesize) != pagesize) + return 3; + close (fd); + + /* Next, check that the tail of a page is zero-filled. File must have + non-zero length, otherwise we risk SIGBUS for entire page. */ + fd2 = open ("conftest.txt", O_RDWR | O_CREAT | O_TRUNC, 0600); + if (fd2 < 0) + return 4; + cdata2 = ""; + if (write (fd2, cdata2, 1) != 1) + return 5; + data2 = (char *) mmap (0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0L); + if (data2 == MAP_FAILED) + return 6; + for (i = 0; i < pagesize; ++i) + if (*(data2 + i)) + return 7; + close (fd2); + if (munmap (data2, pagesize)) + return 8; + + /* Next, try to mmap the file at a fixed address which already has + something else allocated at it. If we can, also make sure that + we see the same garbage. */ + fd = open ("conftest.mmap", O_RDWR); + if (fd < 0) + return 9; + if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + return 10; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + return 11; + + /* Finally, make sure that changes to the mapped area do not + percolate back to the file as seen by read(). (This is a bug on + some variants of i386 svr4.0.) */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = (char *) malloc (pagesize); + if (!data3) + return 12; + if (read (fd, data3, pagesize) != pagesize) + return 13; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + return 14; + close (fd); + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_mmap_fixed_mapped=yes +else + ac_cv_func_mmap_fixed_mapped=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mmap_fixed_mapped" >&5 +$as_echo "$ac_cv_func_mmap_fixed_mapped" >&6; } +if test $ac_cv_func_mmap_fixed_mapped = yes; then + +$as_echo "#define HAVE_MMAP 1" >>confdefs.h + +fi +rm -f conftest.mmap conftest.txt + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether integer division by zero raises SIGFPE" >&5 +$as_echo_n "checking whether integer division by zero raises SIGFPE... " >&6; } +if ${gt_cv_int_divbyzero_sigfpe+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gt_cv_int_divbyzero_sigfpe= + case "$host_os" in + macos* | darwin[6-9]* | darwin[1-9][0-9]*) + # On MacOS X 10.2 or newer, just assume the same as when cross- + # compiling. If we were to perform the real test, 1 Crash Report + # dialog window would pop up. + case "$host_cpu" in + i[34567]86 | x86_64) + gt_cv_int_divbyzero_sigfpe="guessing yes" ;; + esac + ;; + esac + if test -z "$gt_cv_int_divbyzero_sigfpe"; then + if test "$cross_compiling" = yes; then : + + # Guess based on the CPU. + case "$host_cpu" in + alpha* | i[34567]86 | x86_64 | m68k | s390*) + gt_cv_int_divbyzero_sigfpe="guessing yes";; + *) + gt_cv_int_divbyzero_sigfpe="guessing no";; + esac + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +static void +sigfpe_handler (int sig) +{ + /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */ + exit (sig != SIGFPE); +} + +int x = 1; +int y = 0; +int z; +int nan; + +int main () +{ + signal (SIGFPE, sigfpe_handler); +/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */ +#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP) + signal (SIGTRAP, sigfpe_handler); +#endif +/* Linux/SPARC yields signal SIGILL. */ +#if defined (__sparc__) && defined (__linux__) + signal (SIGILL, sigfpe_handler); +#endif + + z = x / y; + nan = y / y; + exit (1); +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + gt_cv_int_divbyzero_sigfpe=yes +else + gt_cv_int_divbyzero_sigfpe=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_int_divbyzero_sigfpe" >&5 +$as_echo "$gt_cv_int_divbyzero_sigfpe" >&6; } + case "$gt_cv_int_divbyzero_sigfpe" in + *yes) value=1;; + *) value=0;; + esac + +cat >>confdefs.h <<_ACEOF +#define INTDIV0_RAISES_SIGFPE $value +_ACEOF + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inttypes.h" >&5 +$as_echo_n "checking for inttypes.h... " >&6; } +if ${gl_cv_header_inttypes_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +int +main () +{ +uintmax_t i = (uintmax_t) -1; return !i; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gl_cv_header_inttypes_h=yes +else + gl_cv_header_inttypes_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_header_inttypes_h" >&5 +$as_echo "$gl_cv_header_inttypes_h" >&6; } + if test $gl_cv_header_inttypes_h = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_INTTYPES_H_WITH_UINTMAX 1 +_ACEOF + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unsigned long long int" >&5 +$as_echo_n "checking for unsigned long long int... " >&6; } +if ${ac_cv_type_unsigned_long_long_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + /* Test preprocessor. */ + #if ! (-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + error in preprocessor; + #endif + #if ! (18446744073709551615ULL <= -1ull) + error in preprocessor; + #endif + /* Test literals. */ + long long int ll = 9223372036854775807ll; + long long int nll = -9223372036854775807LL; + unsigned long long int ull = 18446744073709551615ULL; + /* Test constant expressions. */ + typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + ? 1 : -1)]; + typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 + ? 1 : -1)]; + int i = 63; +int +main () +{ +/* Test availability of runtime routines for shift and division. */ + long long int llmax = 9223372036854775807ll; + unsigned long long int ullmax = 18446744073709551615ull; + return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) + | (llmax / ll) | (llmax % ll) + | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) + | (ullmax / ull) | (ullmax % ull)); + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_type_unsigned_long_long_int=yes +else + ac_cv_type_unsigned_long_long_int=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_unsigned_long_long_int" >&5 +$as_echo "$ac_cv_type_unsigned_long_long_int" >&6; } + if test $ac_cv_type_unsigned_long_long_int = yes; then + +$as_echo "#define HAVE_UNSIGNED_LONG_LONG_INT 1" >>confdefs.h + + fi + + + + + if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then + + test $ac_cv_type_unsigned_long_long_int = yes \ + && ac_type='unsigned long long' \ + || ac_type='unsigned long' + +cat >>confdefs.h <<_ACEOF +#define uintmax_t $ac_type +_ACEOF + + else + +$as_echo "#define HAVE_UINTMAX_T 1" >>confdefs.h + + fi + + + for ac_header in inttypes.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "inttypes.h" "ac_cv_header_inttypes_h" "$ac_includes_default" +if test "x$ac_cv_header_inttypes_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_INTTYPES_H 1 +_ACEOF + +fi + +done + + if test $ac_cv_header_inttypes_h = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the inttypes.h PRIxNN macros are broken" >&5 +$as_echo_n "checking whether the inttypes.h PRIxNN macros are broken... " >&6; } +if ${gt_cv_inttypes_pri_broken+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#ifdef PRId32 +char *p = PRId32; +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gt_cv_inttypes_pri_broken=no +else + gt_cv_inttypes_pri_broken=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_inttypes_pri_broken" >&5 +$as_echo "$gt_cv_inttypes_pri_broken" >&6; } + fi + if test "$gt_cv_inttypes_pri_broken" = yes; then + +cat >>confdefs.h <<_ACEOF +#define PRI_MACROS_BROKEN 1 +_ACEOF + + PRI_MACROS_BROKEN=1 + else + PRI_MACROS_BROKEN=0 + fi + + + + + + + # Check whether --enable-threads was given. +if test "${enable_threads+set}" = set; then : + enableval=$enable_threads; gl_use_threads=$enableval +else + case "$host_os" in + osf*) gl_use_threads=no ;; + *) gl_use_threads=yes ;; + esac + +fi + + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # For using : + case "$host_os" in + osf*) + # On OSF/1, the compiler needs the flag -D_REENTRANT so that it + # groks . cc also understands the flag -pthread, but + # we don't use it because 1. gcc-2.95 doesn't understand -pthread, + # 2. putting a flag into CPPFLAGS that has an effect on the linker + # causes the AC_TRY_LINK test below to succeed unexpectedly, + # leading to wrong values of LIBTHREAD and LTLIBTHREAD. + CPPFLAGS="$CPPFLAGS -D_REENTRANT" + ;; + esac + # Some systems optimize for single-threaded programs by default, and + # need special flags to disable these optimizations. For example, the + # definition of 'errno' in . + case "$host_os" in + aix* | freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;; + solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;; + esac + fi + + + + + + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by GCC" >&5 +$as_echo_n "checking for ld used by GCC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${acl_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break ;; + *) + test "$with_gnu_ld" != yes && break ;; + esac + fi + done + IFS="$ac_save_ifs" +else + acl_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$acl_cv_path_LD" +if test -n "$LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${acl_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU ld's only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$acl_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$acl_cv_prog_gnu_ld + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shared library run path origin" >&5 +$as_echo_n "checking for shared library run path origin... " >&6; } +if ${acl_cv_rpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_rpath" >&5 +$as_echo "$acl_cv_rpath" >&6; } + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + # Check whether --enable-rpath was given. +if test "${enable_rpath+set}" = set; then : + enableval=$enable_rpath; : +else + enable_rpath=yes +fi + + + + acl_libdirstem=lib + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + + + + gl_threads_api=none + LIBTHREAD= + LTLIBTHREAD= + LIBMULTITHREAD= + LTLIBMULTITHREAD= + if test "$gl_use_threads" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether imported symbols can be declared weak" >&5 +$as_echo_n "checking whether imported symbols can be declared weak... " >&6; } + gl_have_weak=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +extern void xyzzy (); +#pragma weak xyzzy +int +main () +{ +xyzzy(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_have_weak=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_have_weak" >&5 +$as_echo "$gl_have_weak" >&6; } + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # On OSF/1, the compiler needs the flag -pthread or -D_REENTRANT so that + # it groks . It's added above, in gl_LOCK_EARLY_BODY. + ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" +if test "x$ac_cv_header_pthread_h" = xyes; then : + gl_have_pthread_h=yes +else + gl_have_pthread_h=no +fi + + + if test "$gl_have_pthread_h" = yes; then + # Other possible tests: + # -lpthreads (FSU threads, PCthreads) + # -lgthreads + gl_have_pthread= + # Test whether both pthread_mutex_lock and pthread_mutexattr_init exist + # in libc. IRIX 6.5 has the first one in both libc and libpthread, but + # the second one only in libpthread, and lock.c needs it. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +pthread_mutex_lock((pthread_mutex_t*)0); + pthread_mutexattr_init((pthread_mutexattr_t*)0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_have_pthread=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + # Test for libpthread by looking for pthread_kill. (Not pthread_self, + # since it is defined as a macro on OSF/1.) + if test -n "$gl_have_pthread"; then + # The program links fine without libpthread. But it may actually + # need to link with libpthread in order to create multiple threads. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_kill in -lpthread" >&5 +$as_echo_n "checking for pthread_kill in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_pthread_kill+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_kill (); +int +main () +{ +return pthread_kill (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread_pthread_kill=yes +else + ac_cv_lib_pthread_pthread_kill=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_kill" >&5 +$as_echo "$ac_cv_lib_pthread_pthread_kill" >&6; } +if test "x$ac_cv_lib_pthread_pthread_kill" = xyes; then : + LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread + # On Solaris and HP-UX, most pthread functions exist also in libc. + # Therefore pthread_in_use() needs to actually try to create a + # thread: pthread_create from libc will fail, whereas + # pthread_create will actually create a thread. + case "$host_os" in + solaris* | hpux*) + +$as_echo "#define PTHREAD_IN_USE_DETECTION_HARD 1" >>confdefs.h + + esac + +fi + + else + # Some library is needed. Try libpthread and libc_r. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_kill in -lpthread" >&5 +$as_echo_n "checking for pthread_kill in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_pthread_kill+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_kill (); +int +main () +{ +return pthread_kill (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread_pthread_kill=yes +else + ac_cv_lib_pthread_pthread_kill=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_kill" >&5 +$as_echo "$ac_cv_lib_pthread_pthread_kill" >&6; } +if test "x$ac_cv_lib_pthread_pthread_kill" = xyes; then : + gl_have_pthread=yes + LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread + LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread +fi + + if test -z "$gl_have_pthread"; then + # For FreeBSD 4. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_kill in -lc_r" >&5 +$as_echo_n "checking for pthread_kill in -lc_r... " >&6; } +if ${ac_cv_lib_c_r_pthread_kill+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc_r $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_kill (); +int +main () +{ +return pthread_kill (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_c_r_pthread_kill=yes +else + ac_cv_lib_c_r_pthread_kill=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_kill" >&5 +$as_echo "$ac_cv_lib_c_r_pthread_kill" >&6; } +if test "x$ac_cv_lib_c_r_pthread_kill" = xyes; then : + gl_have_pthread=yes + LIBTHREAD=-lc_r LTLIBTHREAD=-lc_r + LIBMULTITHREAD=-lc_r LTLIBMULTITHREAD=-lc_r +fi + + fi + fi + if test -n "$gl_have_pthread"; then + gl_threads_api=posix + +$as_echo "#define USE_POSIX_THREADS 1" >>confdefs.h + + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if test $gl_have_weak = yes; then + +$as_echo "#define USE_POSIX_THREADS_WEAK 1" >>confdefs.h + + LIBTHREAD= + LTLIBTHREAD= + fi + fi + # OSF/1 4.0 and MacOS X 10.1 lack the pthread_rwlock_t type and the + # pthread_rwlock_* functions. + ac_fn_c_check_type "$LINENO" "pthread_rwlock_t" "ac_cv_type_pthread_rwlock_t" "#include +" +if test "x$ac_cv_type_pthread_rwlock_t" = xyes; then : + +$as_echo "#define HAVE_PTHREAD_RWLOCK 1" >>confdefs.h + +fi + + # glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +#if __FreeBSD__ == 4 +error "No, in FreeBSD 4.0 recursive mutexes actually don't work." +#else +int x = (int)PTHREAD_MUTEX_RECURSIVE; +return !x; +#endif + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_PTHREAD_MUTEX_RECURSIVE 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = solaris; then + gl_have_solaristhread= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lthread" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +int +main () +{ +thr_self(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_have_solaristhread=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gl_save_LIBS" + if test -n "$gl_have_solaristhread"; then + gl_threads_api=solaris + LIBTHREAD=-lthread + LTLIBTHREAD=-lthread + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + +$as_echo "#define USE_SOLARIS_THREADS 1" >>confdefs.h + + if test $gl_have_weak = yes; then + +$as_echo "#define USE_SOLARIS_THREADS_WEAK 1" >>confdefs.h + + LIBTHREAD= + LTLIBTHREAD= + fi + fi + fi + fi + if test "$gl_use_threads" = pth; then + gl_save_CPPFLAGS="$CPPFLAGS" + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libpth" >&5 +$as_echo_n "checking how to link with libpth... " >&6; } +if ${ac_cv_libpth_libs+:} false; then : + $as_echo_n "(cached) " >&6 +else + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libpth-prefix was given. +if test "${with_libpth_prefix+set}" = set; then : + withval=$with_libpth_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi + +fi + + LIBPTH= + LTLIBPTH= + INCPTH= + LIBPTH_PREFIX= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='pth ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBPTH="${LIBPTH}${LIBPTH:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBPTH="${LTLIBPTH}${LTLIBPTH:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBPTH; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBPTH="${LTLIBPTH}${LTLIBPTH:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then + LIBPTH="${LIBPTH}${LIBPTH:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBPTH="${LIBPTH}${LIBPTH:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBPTH="${LIBPTH}${LIBPTH:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBPTH; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBPTH="${LIBPTH}${LIBPTH:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBPTH="${LIBPTH}${LIBPTH:+ }$found_so" + else + LIBPTH="${LIBPTH}${LIBPTH:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBPTH="${LIBPTH}${LIBPTH:+ }$found_a" + else + LIBPTH="${LIBPTH}${LIBPTH:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + LIBPTH_PREFIX="$basedir" + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCPTH; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCPTH="${INCPTH}${INCPTH:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBPTH; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBPTH="${LIBPTH}${LIBPTH:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBPTH; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBPTH="${LTLIBPTH}${LTLIBPTH:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBPTH="${LIBPTH}${LIBPTH:+ }$dep" + LTLIBPTH="${LTLIBPTH}${LTLIBPTH:+ }$dep" + ;; + esac + done + fi + else + LIBPTH="${LIBPTH}${LIBPTH:+ }-l$name" + LTLIBPTH="${LTLIBPTH}${LTLIBPTH:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBPTH="${LIBPTH}${LIBPTH:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBPTH="${LIBPTH}${LIBPTH:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBPTH="${LTLIBPTH}${LTLIBPTH:+ }-R$found_dir" + done + fi + + ac_cv_libpth_libs="$LIBPTH" + ac_cv_libpth_ltlibs="$LTLIBPTH" + ac_cv_libpth_cppflags="$INCPTH" + ac_cv_libpth_prefix="$LIBPTH_PREFIX" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libpth_libs" >&5 +$as_echo "$ac_cv_libpth_libs" >&6; } + LIBPTH="$ac_cv_libpth_libs" + LTLIBPTH="$ac_cv_libpth_ltlibs" + INCPTH="$ac_cv_libpth_cppflags" + LIBPTH_PREFIX="$ac_cv_libpth_prefix" + + for element in $INCPTH; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + + + HAVE_LIBPTH=yes + + + + gl_have_pth= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lpth" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +pth_self(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_have_pth=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gl_save_LIBS" + if test -n "$gl_have_pth"; then + gl_threads_api=pth + LIBTHREAD="$LIBPTH" + LTLIBTHREAD="$LTLIBPTH" + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + +$as_echo "#define USE_PTH_THREADS 1" >>confdefs.h + + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if test $gl_have_weak = yes; then + +$as_echo "#define USE_PTH_THREADS_WEAK 1" >>confdefs.h + + LIBTHREAD= + LTLIBTHREAD= + fi + fi + else + CPPFLAGS="$gl_save_CPPFLAGS" + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = win32; then + if { case "$host_os" in + mingw*) true;; + *) false;; + esac + }; then + gl_threads_api=win32 + +$as_echo "#define USE_WIN32_THREADS 1" >>confdefs.h + + fi + fi + fi + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for multithread API to use" >&5 +$as_echo_n "checking for multithread API to use... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_threads_api" >&5 +$as_echo "$gl_threads_api" >&6; } + + + + + + + + + + + + + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libiconv-prefix was given. +if test "${with_libiconv_prefix+set}" = set; then : + withval=$with_libiconv_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi + +fi + + LIBICONV= + LTLIBICONV= + INCICONV= + LIBICONV_PREFIX= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='iconv ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + LIBICONV_PREFIX="$basedir" + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBICONV="${LIBICONV}${LIBICONV:+ }$dep" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep" + ;; + esac + done + fi + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir" + done + fi + + + + + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (int a) { a = __builtin_expect (a, 10); return a == 10 ? 0 : 1; } +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +$as_echo "#define HAVE_BUILTIN_EXPECT 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + for ac_header in argz.h inttypes.h limits.h unistd.h sys/param.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + for ac_func in getcwd getegid geteuid getgid getuid mempcpy munmap \ + stpcpy strcasecmp strdup strtoul tsearch argz_count argz_stringify \ + argz_next __fsetlocking +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether feof_unlocked is declared" >&5 +$as_echo_n "checking whether feof_unlocked is declared... " >&6; } +if ${ac_cv_have_decl_feof_unlocked+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + +#ifndef feof_unlocked + char *p = (char *) feof_unlocked; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_have_decl_feof_unlocked=yes +else + ac_cv_have_decl_feof_unlocked=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_decl_feof_unlocked" >&5 +$as_echo "$ac_cv_have_decl_feof_unlocked" >&6; } + if test $ac_cv_have_decl_feof_unlocked = yes; then + gt_value=1 + else + gt_value=0 + fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_FEOF_UNLOCKED $gt_value +_ACEOF + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether fgets_unlocked is declared" >&5 +$as_echo_n "checking whether fgets_unlocked is declared... " >&6; } +if ${ac_cv_have_decl_fgets_unlocked+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + +#ifndef fgets_unlocked + char *p = (char *) fgets_unlocked; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_have_decl_fgets_unlocked=yes +else + ac_cv_have_decl_fgets_unlocked=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_decl_fgets_unlocked" >&5 +$as_echo "$ac_cv_have_decl_fgets_unlocked" >&6; } + if test $ac_cv_have_decl_fgets_unlocked = yes; then + gt_value=1 + else + gt_value=0 + fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_FGETS_UNLOCKED $gt_value +_ACEOF + + + + + + + + + am_save_CPPFLAGS="$CPPFLAGS" + + for element in $INCICONV; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 +$as_echo_n "checking for iconv... " >&6; } +if ${am_cv_func_iconv+:} false; then : + $as_echo_n "(cached) " >&6 +else + + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_lib_iconv=yes + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$am_save_LIBS" + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5 +$as_echo "$am_cv_func_iconv" >&6; } + if test "$am_cv_func_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working iconv" >&5 +$as_echo_n "checking for working iconv... " >&6; } +if ${am_cv_func_iconv_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + if test "$cross_compiling" = yes; then : + case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int main () +{ + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + return 1; + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + return 1; + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + return 1; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + am_cv_func_iconv_works=yes +else + am_cv_func_iconv_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + LIBS="$am_save_LIBS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv_works" >&5 +$as_echo "$am_cv_func_iconv_works" >&6; } + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + +$as_echo "#define HAVE_ICONV 1" >>confdefs.h + + fi + if test "$am_cv_lib_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 +$as_echo_n "checking how to link with libiconv... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 +$as_echo "$LIBICONV" >&6; } + else + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + + + + if test "$am_cv_func_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv declaration" >&5 +$as_echo_n "checking for iconv declaration... " >&6; } + if ${am_cv_proto_iconv+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + am_cv_proto_iconv_arg1="" +else + am_cv_proto_iconv_arg1="const" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);" +fi + + am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ac_t:- + }$am_cv_proto_iconv" >&5 +$as_echo "${ac_t:- + }$am_cv_proto_iconv" >&6; } + +cat >>confdefs.h <<_ACEOF +#define ICONV_CONST $am_cv_proto_iconv_arg1 +_ACEOF + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NL_LOCALE_NAME macro" >&5 +$as_echo_n "checking for NL_LOCALE_NAME macro... " >&6; } +if ${gt_cv_nl_locale_name+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +int +main () +{ +char* cs = nl_langinfo(_NL_LOCALE_NAME(LC_MESSAGES)); + return !cs; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_nl_locale_name=yes +else + gt_cv_nl_locale_name=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_nl_locale_name" >&5 +$as_echo "$gt_cv_nl_locale_name" >&6; } + if test $gt_cv_nl_locale_name = yes; then + +$as_echo "#define HAVE_NL_LOCALE_NAME 1" >>confdefs.h + + fi + + for ac_prog in bison +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_INTLBISON+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$INTLBISON"; then + ac_cv_prog_INTLBISON="$INTLBISON" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_INTLBISON="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +INTLBISON=$ac_cv_prog_INTLBISON +if test -n "$INTLBISON"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLBISON" >&5 +$as_echo "$INTLBISON" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$INTLBISON" && break +done + + if test -z "$INTLBISON"; then + ac_verc_fail=yes + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of bison" >&5 +$as_echo_n "checking version of bison... " >&6; } + ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` + case $ac_prog_version in + '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; + 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) + ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; + *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_prog_version" >&5 +$as_echo "$ac_prog_version" >&6; } + fi + if test $ac_verc_fail = yes; then + INTLBISON=: + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for long long int" >&5 +$as_echo_n "checking for long long int... " >&6; } +if ${ac_cv_type_long_long_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + /* Test preprocessor. */ + #if ! (-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + error in preprocessor; + #endif + #if ! (18446744073709551615ULL <= -1ull) + error in preprocessor; + #endif + /* Test literals. */ + long long int ll = 9223372036854775807ll; + long long int nll = -9223372036854775807LL; + unsigned long long int ull = 18446744073709551615ULL; + /* Test constant expressions. */ + typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + ? 1 : -1)]; + typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 + ? 1 : -1)]; + int i = 63; +int +main () +{ +/* Test availability of runtime routines for shift and division. */ + long long int llmax = 9223372036854775807ll; + unsigned long long int ullmax = 18446744073709551615ull; + return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) + | (llmax / ll) | (llmax % ll) + | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) + | (ullmax / ull) | (ullmax % ull)); + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if test "$cross_compiling" = yes; then : + ac_cv_type_long_long_int=yes +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #ifndef LLONG_MAX + # define HALF \ + (1LL << (sizeof (long long int) * CHAR_BIT - 2)) + # define LLONG_MAX (HALF - 1 + HALF) + #endif +int +main () +{ +long long int n = 1; + int i; + for (i = 0; ; i++) + { + long long int m = n << i; + if (m >> i != n) + return 1; + if (LLONG_MAX / 2 < m) + break; + } + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_type_long_long_int=yes +else + ac_cv_type_long_long_int=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +else + ac_cv_type_long_long_int=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_long_int" >&5 +$as_echo "$ac_cv_type_long_long_int" >&6; } + if test $ac_cv_type_long_long_int = yes; then + +$as_echo "#define HAVE_LONG_LONG_INT 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wchar_t" >&5 +$as_echo_n "checking for wchar_t... " >&6; } +if ${gt_cv_c_wchar_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + wchar_t foo = (wchar_t)'\0'; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gt_cv_c_wchar_t=yes +else + gt_cv_c_wchar_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_c_wchar_t" >&5 +$as_echo "$gt_cv_c_wchar_t" >&6; } + if test $gt_cv_c_wchar_t = yes; then + +$as_echo "#define HAVE_WCHAR_T 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wint_t" >&5 +$as_echo_n "checking for wint_t... " >&6; } +if ${gt_cv_c_wint_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Tru64 with Desktop Toolkit C has a bug: must be included before + . + BSD/OS 4.0.1 has a bug: , and must be included + before . */ +#include +#include +#include +#include + wint_t foo = (wchar_t)'\0'; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gt_cv_c_wint_t=yes +else + gt_cv_c_wint_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_c_wint_t" >&5 +$as_echo "$gt_cv_c_wint_t" >&6; } + if test $gt_cv_c_wint_t = yes; then + +$as_echo "#define HAVE_WINT_T 1" >>confdefs.h + + fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for intmax_t" >&5 +$as_echo_n "checking for intmax_t... " >&6; } +if ${gt_cv_c_intmax_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#if HAVE_STDINT_H_WITH_UINTMAX +#include +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +#include +#endif + +int +main () +{ +intmax_t x = -1; + return !x; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gt_cv_c_intmax_t=yes +else + gt_cv_c_intmax_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_c_intmax_t" >&5 +$as_echo "$gt_cv_c_intmax_t" >&6; } + if test $gt_cv_c_intmax_t = yes; then + +$as_echo "#define HAVE_INTMAX_T 1" >>confdefs.h + + fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether printf() supports POSIX/XSI format strings" >&5 +$as_echo_n "checking whether printf() supports POSIX/XSI format strings... " >&6; } +if ${gt_cv_func_printf_posix+:} false; then : + $as_echo_n "(cached) " >&6 +else + + if test "$cross_compiling" = yes; then : + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if defined __NetBSD__ || defined __BEOS__ || defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ + notposix +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "notposix" >/dev/null 2>&1; then : + gt_cv_func_printf_posix="guessing no" +else + gt_cv_func_printf_posix="guessing yes" +fi +rm -f conftest* + + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +/* The string "%2$d %1$d", with dollar characters protected from the shell's + dollar expansion (possibly an autoconf bug). */ +static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' }; +static char buf[100]; +int main () +{ + sprintf (buf, format, 33, 55); + return (strcmp (buf, "55 33") != 0); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + gt_cv_func_printf_posix=yes +else + gt_cv_func_printf_posix=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_printf_posix" >&5 +$as_echo "$gt_cv_func_printf_posix" >&6; } + case $gt_cv_func_printf_posix in + *yes) + +$as_echo "#define HAVE_POSIX_PRINTF 1" >>confdefs.h + + ;; + esac + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C Library 2.1 or newer" >&5 +$as_echo_n "checking whether we are using the GNU C Library 2.1 or newer... " >&6; } +if ${ac_cv_gnu_library_2_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) + Lucky GNU user + #endif +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "Lucky GNU user" >/dev/null 2>&1; then : + ac_cv_gnu_library_2_1=yes +else + ac_cv_gnu_library_2_1=no +fi +rm -f conftest* + + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_gnu_library_2_1" >&5 +$as_echo "$ac_cv_gnu_library_2_1" >&6; } + + GLIBC21="$ac_cv_gnu_library_2_1" + + + + for ac_header in stdint.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default" +if test "x$ac_cv_header_stdint_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDINT_H 1 +_ACEOF + +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SIZE_MAX" >&5 +$as_echo_n "checking for SIZE_MAX... " >&6; } + if ${gl_cv_size_max+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_cv_size_max= + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#if HAVE_STDINT_H +#include +#endif +#ifdef SIZE_MAX +Found it +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "Found it" >/dev/null 2>&1; then : + gl_cv_size_max=yes +fi +rm -f conftest* + + if test -z "$gl_cv_size_max"; then + if ac_fn_c_compute_int "$LINENO" "sizeof (size_t) * CHAR_BIT - 1" "size_t_bits_minus_1" "#include +#include "; then : + +else + size_t_bits_minus_1= +fi + + if ac_fn_c_compute_int "$LINENO" "sizeof (size_t) <= sizeof (unsigned int)" "fits_in_uint" "#include "; then : + +else + fits_in_uint= +fi + + if test -n "$size_t_bits_minus_1" && test -n "$fits_in_uint"; then + if test $fits_in_uint = 1; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + extern size_t foo; + extern unsigned long foo; + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + fits_in_uint=0 +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $fits_in_uint = 1; then + gl_cv_size_max="(((1U << $size_t_bits_minus_1) - 1) * 2 + 1)" + else + gl_cv_size_max="(((1UL << $size_t_bits_minus_1) - 1) * 2 + 1)" + fi + else + gl_cv_size_max='((size_t)~(size_t)0)' + fi + fi + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_size_max" >&5 +$as_echo "$gl_cv_size_max" >&6; } + if test "$gl_cv_size_max" != yes; then + +cat >>confdefs.h <<_ACEOF +#define SIZE_MAX $gl_cv_size_max +_ACEOF + + fi + + + + + for ac_header in stdint.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default" +if test "x$ac_cv_header_stdint_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDINT_H 1 +_ACEOF + +fi + +done + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFPreferencesCopyAppValue" >&5 +$as_echo_n "checking for CFPreferencesCopyAppValue... " >&6; } +if ${gt_cv_func_CFPreferencesCopyAppValue+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +CFPreferencesCopyAppValue(NULL, NULL) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_CFPreferencesCopyAppValue=yes +else + gt_cv_func_CFPreferencesCopyAppValue=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFPreferencesCopyAppValue" >&5 +$as_echo "$gt_cv_func_CFPreferencesCopyAppValue" >&6; } + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + +$as_echo "#define HAVE_CFPREFERENCESCOPYAPPVALUE 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFLocaleCopyCurrent" >&5 +$as_echo_n "checking for CFLocaleCopyCurrent... " >&6; } +if ${gt_cv_func_CFLocaleCopyCurrent+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +CFLocaleCopyCurrent(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_CFLocaleCopyCurrent=yes +else + gt_cv_func_CFLocaleCopyCurrent=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFLocaleCopyCurrent" >&5 +$as_echo "$gt_cv_func_CFLocaleCopyCurrent" >&6; } + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + +$as_echo "#define HAVE_CFLOCALECOPYCURRENT 1" >>confdefs.h + + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + + + + + + + + ac_fn_c_check_type "$LINENO" "ptrdiff_t" "ac_cv_type_ptrdiff_t" "$ac_includes_default" +if test "x$ac_cv_type_ptrdiff_t" = xyes; then : + +else + +$as_echo "#define ptrdiff_t long" >>confdefs.h + + +fi + + for ac_header in stddef.h stdlib.h string.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + for ac_func in asprintf fwprintf putenv setenv setlocale snprintf wcslen +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether _snprintf is declared" >&5 +$as_echo_n "checking whether _snprintf is declared... " >&6; } +if ${ac_cv_have_decl__snprintf+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + +#ifndef _snprintf + char *p = (char *) _snprintf; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_have_decl__snprintf=yes +else + ac_cv_have_decl__snprintf=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_decl__snprintf" >&5 +$as_echo "$ac_cv_have_decl__snprintf" >&6; } + if test $ac_cv_have_decl__snprintf = yes; then + gt_value=1 + else + gt_value=0 + fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL__SNPRINTF $gt_value +_ACEOF + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether _snwprintf is declared" >&5 +$as_echo_n "checking whether _snwprintf is declared... " >&6; } +if ${ac_cv_have_decl__snwprintf+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + +#ifndef _snwprintf + char *p = (char *) _snwprintf; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_have_decl__snwprintf=yes +else + ac_cv_have_decl__snwprintf=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_decl__snwprintf" >&5 +$as_echo "$ac_cv_have_decl__snwprintf" >&6; } + if test $ac_cv_have_decl__snwprintf = yes; then + gt_value=1 + else + gt_value=0 + fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL__SNWPRINTF $gt_value +_ACEOF + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether getc_unlocked is declared" >&5 +$as_echo_n "checking whether getc_unlocked is declared... " >&6; } +if ${ac_cv_have_decl_getc_unlocked+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + +#ifndef getc_unlocked + char *p = (char *) getc_unlocked; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_have_decl_getc_unlocked=yes +else + ac_cv_have_decl_getc_unlocked=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_decl_getc_unlocked" >&5 +$as_echo "$ac_cv_have_decl_getc_unlocked" >&6; } + if test $ac_cv_have_decl_getc_unlocked = yes; then + gt_value=1 + else + gt_value=0 + fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_GETC_UNLOCKED $gt_value +_ACEOF + + + + case $gt_cv_func_printf_posix in + *yes) HAVE_POSIX_PRINTF=1 ;; + *) HAVE_POSIX_PRINTF=0 ;; + esac + + if test "$ac_cv_func_asprintf" = yes; then + HAVE_ASPRINTF=1 + else + HAVE_ASPRINTF=0 + fi + + if test "$ac_cv_func_snprintf" = yes; then + HAVE_SNPRINTF=1 + else + HAVE_SNPRINTF=0 + fi + + if test "$ac_cv_func_wprintf" = yes; then + HAVE_WPRINTF=1 + else + HAVE_WPRINTF=0 + fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_langinfo and CODESET" >&5 +$as_echo_n "checking for nl_langinfo and CODESET... " >&6; } +if ${am_cv_langinfo_codeset+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +char* cs = nl_langinfo(CODESET); return !cs; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_langinfo_codeset=yes +else + am_cv_langinfo_codeset=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_langinfo_codeset" >&5 +$as_echo "$am_cv_langinfo_codeset" >&6; } + if test $am_cv_langinfo_codeset = yes; then + +$as_echo "#define HAVE_LANGINFO_CODESET 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LC_MESSAGES" >&5 +$as_echo_n "checking for LC_MESSAGES... " >&6; } +if ${gt_cv_val_LC_MESSAGES+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +return LC_MESSAGES + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_val_LC_MESSAGES=yes +else + gt_cv_val_LC_MESSAGES=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_val_LC_MESSAGES" >&5 +$as_echo "$gt_cv_val_LC_MESSAGES" >&6; } + if test $gt_cv_val_LC_MESSAGES = yes; then + +$as_echo "#define HAVE_LC_MESSAGES 1" >>confdefs.h + + fi + + + if test "$enable_shared" = yes; then + case "$host_os" in + mingw* | cygwin*) is_woe32dll=yes ;; + *) is_woe32dll=no ;; + esac + else + is_woe32dll=no + fi + WOE32DLL=$is_woe32dll + + + case "$host_os" in + mingw* | cygwin*) is_woe32=yes ;; + *) is_woe32=no ;; + esac + WOE32=$is_woe32 + + if test $WOE32 = yes; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args. +set dummy ${ac_tool_prefix}windres; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_WINDRES+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$WINDRES"; then + ac_cv_prog_WINDRES="$WINDRES" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_WINDRES="${ac_tool_prefix}windres" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +WINDRES=$ac_cv_prog_WINDRES +if test -n "$WINDRES"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINDRES" >&5 +$as_echo "$WINDRES" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_WINDRES"; then + ac_ct_WINDRES=$WINDRES + # Extract the first word of "windres", so it can be a program name with args. +set dummy windres; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_WINDRES+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_WINDRES"; then + ac_cv_prog_ac_ct_WINDRES="$ac_ct_WINDRES" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_WINDRES="windres" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_WINDRES=$ac_cv_prog_ac_ct_WINDRES +if test -n "$ac_ct_WINDRES"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_WINDRES" >&5 +$as_echo "$ac_ct_WINDRES" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_WINDRES" = x; then + WINDRES="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + WINDRES=$ac_ct_WINDRES + fi +else + WINDRES="$ac_cv_prog_WINDRES" +fi + + fi + + case "$host_os" in + hpux*) LTLIBC="" ;; + *) LTLIBC="-lc" ;; + esac + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFPreferencesCopyAppValue" >&5 +$as_echo_n "checking for CFPreferencesCopyAppValue... " >&6; } +if ${gt_cv_func_CFPreferencesCopyAppValue+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +CFPreferencesCopyAppValue(NULL, NULL) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_CFPreferencesCopyAppValue=yes +else + gt_cv_func_CFPreferencesCopyAppValue=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFPreferencesCopyAppValue" >&5 +$as_echo "$gt_cv_func_CFPreferencesCopyAppValue" >&6; } + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + +$as_echo "#define HAVE_CFPREFERENCESCOPYAPPVALUE 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFLocaleCopyCurrent" >&5 +$as_echo_n "checking for CFLocaleCopyCurrent... " >&6; } +if ${gt_cv_func_CFLocaleCopyCurrent+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +CFLocaleCopyCurrent(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_CFLocaleCopyCurrent=yes +else + gt_cv_func_CFLocaleCopyCurrent=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFLocaleCopyCurrent" >&5 +$as_echo "$gt_cv_func_CFLocaleCopyCurrent" >&6; } + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + +$as_echo "#define HAVE_CFLOCALECOPYCURRENT 1" >>confdefs.h + + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + + + + + + + BUILD_INCLUDED_LIBINTL=no + USE_INCLUDED_LIBINTL=no + + LIBINTL= + LTLIBINTL= + POSUB= + + case " $gt_needs " in + *" need-formatstring-macros "*) gt_api_version=3 ;; + *" need-ngettext "*) gt_api_version=2 ;; + *) gt_api_version=1 ;; + esac + gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" + gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" + + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether included gettext is requested" >&5 +$as_echo_n "checking whether included gettext is requested... " >&6; } + +# Check whether --with-included-gettext was given. +if test "${with_included_gettext+set}" = set; then : + withval=$with_included_gettext; nls_cv_force_use_gnu_gettext=$withval +else + nls_cv_force_use_gnu_gettext=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nls_cv_force_use_gnu_gettext" >&5 +$as_echo "$nls_cv_force_use_gnu_gettext" >&6; } + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + + + if test $gt_api_version -ge 3; then + gt_revision_test_code=' +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +' + else + gt_revision_test_code= + fi + if test $gt_api_version -ge 2; then + gt_expression_test_code=' + * ngettext ("", "", 0)' + else + gt_expression_test_code= + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libc" >&5 +$as_echo_n "checking for GNU gettext in libc... " >&6; } +if eval \${$gt_func_gnugettext_libc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings; +int +main () +{ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$gt_func_gnugettext_libc=yes" +else + eval "$gt_func_gnugettext_libc=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$gt_func_gnugettext_libc + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libintl-prefix was given. +if test "${with_libintl_prefix+set}" = set; then : + withval=$with_libintl_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi + +fi + + LIBINTL= + LTLIBINTL= + INCINTL= + LIBINTL_PREFIX= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='intl ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBINTL="${LIBINTL}${LIBINTL:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_a" + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + LIBINTL_PREFIX="$basedir" + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCINTL="${INCINTL}${INCINTL:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBINTL="${LIBINTL}${LIBINTL:+ }$dep" + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$dep" + ;; + esac + done + fi + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-R$found_dir" + done + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libintl" >&5 +$as_echo_n "checking for GNU gettext in libintl... " >&6; } +if eval \${$gt_func_gnugettext_libintl+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); +int +main () +{ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$gt_func_gnugettext_libintl=yes" +else + eval "$gt_func_gnugettext_libintl=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); +int +main () +{ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + eval "$gt_func_gnugettext_libintl=yes" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS" +fi +eval ac_res=\$$gt_func_gnugettext_libintl + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + fi + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ + || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + + if test "$gt_use_preinstalled_gnugettext" != "yes"; then + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + BUILD_INCLUDED_LIBINTL=yes + USE_INCLUDED_LIBINTL=yes + LIBINTL="\${top_builddir}/intl/libintl.a $LIBICONV $LIBTHREAD" + LTLIBINTL="\${top_builddir}/intl/libintl.a $LTLIBICONV $LTLIBTHREAD" + LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` + fi + + CATOBJEXT= + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + CATOBJEXT=.gmo + fi + + + if test -n "$INTL_MACOSX_LIBS"; then + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" + LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" + fi + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + +$as_echo "#define ENABLE_NLS 1" >>confdefs.h + + else + USE_NLS=no + fi + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use NLS" >&5 +$as_echo_n "checking whether to use NLS... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +$as_echo "$USE_NLS" >&6; } + if test "$USE_NLS" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where the gettext function comes from" >&5 +$as_echo_n "checking where the gettext function comes from... " >&6; } + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_source" >&5 +$as_echo "$gt_source" >&6; } + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libintl" >&5 +$as_echo_n "checking how to link with libintl... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBINTL" >&5 +$as_echo "$LIBINTL" >&6; } + + for element in $INCINTL; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + fi + + +$as_echo "#define HAVE_GETTEXT 1" >>confdefs.h + + +$as_echo "#define HAVE_DCGETTEXT 1" >>confdefs.h + + fi + + POSUB=po + fi + + + if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then + BUILD_INCLUDED_LIBINTL=yes + fi + + + + + + nls_cv_header_intl= + nls_cv_header_libgt= + + DATADIRNAME=share + + + INSTOBJEXT=.mo + + + GENCAT=gencat + + + INTLOBJS= + if test "$USE_INCLUDED_LIBINTL" = yes; then + INTLOBJS="\$(GETTOBJS)" + fi + + + INTL_LIBTOOL_SUFFIX_PREFIX= + + + + INTLLIBS="$LIBINTL" + + + + + + + +GETTEXTDIR="$datadir/locale" + + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4.6' +macro_revision='2.4.6' + + + + + + + + + + + + + +ltmain=$ac_aux_dir/ltmain.sh + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case $ECHO in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n "$lt_cv_sys_max_cmd_len"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test yes != "$GCC"; then + reload_cmds=false + fi + ;; + darwin*) + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[012][,.]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + pic_mode=default +fi + + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +func_cc_basename $compiler +cc_basename=$func_cc_basename_result + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac +fi + +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC=$CC +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test yes = "$GCC"; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + lt_prog_compiler_pic='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_pic_works"; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test yes = "$lt_cv_prog_compiler_static_works"; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + 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 yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + link_all_deplibs=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # 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. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='$wl--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + 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 + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test no = "$ld_shlibs"; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + 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 + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + 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 + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + export_dynamic_flag_spec='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + 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. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + 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 + export_dynamic_flag_spec='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + # 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 yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='$wl-E' + + # 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*) + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + link_all_deplibs=no + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' + else + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + + osf3*) + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='$wl-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='$wl-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='$wl-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test no = "$ld_shlibs" && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + + + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[4-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[23].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test yes = "$hardcode_automatic"; then + + # We can hardcode non-existent directories. + if test no != "$hardcode_direct" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen=shl_load +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen=dlopen +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test yes = "$cross_compiling"; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report what library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC + + + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5 +$as_echo_n "checking for X... " >&6; } + + +# Check whether --with-x was given. +if test "${with_x+set}" = set; then : + withval=$with_x; +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + case $x_includes,$x_libraries in #( + *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( + *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then : + $as_echo_n "(cached) " >&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no ac_x_libraries=no +rm -f -r conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + cat >Imakefile <<'_ACEOF' +incroot: + @echo incroot='${INCROOT}' +usrlibdir: + @echo usrlibdir='${USRLIBDIR}' +libdir: + @echo libdir='${LIBDIR}' +_ACEOF + if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. + for ac_var in incroot usrlibdir libdir; do + eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" + done + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl dylib la dll; do + if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && + test -f "$ac_im_libdir/libX11.$ac_extension"; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ac_x_includes= ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /usr/lib64 | /lib | /lib64) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -f -r conftest.dir +fi + +# Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R7/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R7 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R7/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R7 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Xlib.h. + # First, try using that file with no special directory specified. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # We can compile using X headers with no special include directory. +ac_x_includes= +else + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Xlib.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lX11 $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +XrmInitialize () + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + LIBS=$ac_save_LIBS +for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl dylib la dll; do + if test -r "$ac_dir/libX11.$ac_extension"; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +case $ac_x_includes,$ac_x_libraries in #( + no,* | *,no | *\'*) + # Didn't find X, or a directory has "'" in its name. + ac_cv_have_x="have_x=no";; #( + *) + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$ac_x_includes'\ + ac_x_libraries='$ac_x_libraries'" +esac +fi +;; #( + *) have_x=yes;; + esac + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5 +$as_echo "$have_x" >&6; } + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$x_includes'\ + ac_x_libraries='$x_libraries'" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5 +$as_echo "libraries $x_libraries, headers $x_includes" >&6; } +fi + +if test "$no_x" = yes; then + # Not all programs may use this symbol, but it does not hurt to define it. + +$as_echo "#define X_DISPLAY_MISSING 1" >>confdefs.h + + X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= +else + if test -n "$x_includes"; then + X_CFLAGS="$X_CFLAGS -I$x_includes" + fi + + # It would also be nice to do this for all -L options, not just this one. + if test -n "$x_libraries"; then + X_LIBS="$X_LIBS -L$x_libraries" + # For Solaris; some versions of Sun CC require a space after -R and + # others require no space. Words are not sufficient . . . . + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -R must be followed by a space" >&5 +$as_echo_n "checking whether -R must be followed by a space... " >&6; } + ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" + ac_xsave_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + X_LIBS="$X_LIBS -R$x_libraries" +else + LIBS="$ac_xsave_LIBS -R $x_libraries" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + X_LIBS="$X_LIBS -R $x_libraries" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: neither works" >&5 +$as_echo "neither works" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_c_werror_flag=$ac_xsave_c_werror_flag + LIBS=$ac_xsave_LIBS + fi + + # Check for system-dependent libraries X programs must link with. + # Do this before checking for the system-independent R6 libraries + # (-lICE), since we may need -lsocket or whatever for X linking. + + if test "$ISC" = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" + else + # Martyn Johnson says this is needed for Ultrix, if the X + # libraries were built with DECnet support. And Karl Berry says + # the Alpha needs dnet_stub (dnet does not exist). + ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XOpenDisplay (); +int +main () +{ +return XOpenDisplay (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5 +$as_echo_n "checking for dnet_ntoa in -ldnet... " >&6; } +if ${ac_cv_lib_dnet_dnet_ntoa+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dnet_ntoa (); +int +main () +{ +return dnet_ntoa (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dnet_dnet_ntoa=yes +else + ac_cv_lib_dnet_dnet_ntoa=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 +$as_echo "$ac_cv_lib_dnet_dnet_ntoa" >&6; } +if test "x$ac_cv_lib_dnet_dnet_ntoa" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" +fi + + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5 +$as_echo_n "checking for dnet_ntoa in -ldnet_stub... " >&6; } +if ${ac_cv_lib_dnet_stub_dnet_ntoa+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet_stub $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dnet_ntoa (); +int +main () +{ +return dnet_ntoa (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dnet_stub_dnet_ntoa=yes +else + ac_cv_lib_dnet_stub_dnet_ntoa=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 +$as_echo "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; } +if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" +fi + + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$ac_xsave_LIBS" + + # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, + # to get the SysV transport functions. + # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) + # needs -lnsl. + # The nsl library prevents programs from opening the X display + # on Irix 5.2, according to T.E. Dickey. + # The functions gethostbyname, getservbyname, and inet_addr are + # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. + ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" +if test "x$ac_cv_func_gethostbyname" = xyes; then : + +fi + + if test $ac_cv_func_gethostbyname = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 +$as_echo_n "checking for gethostbyname in -lnsl... " >&6; } +if ${ac_cv_lib_nsl_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_nsl_gethostbyname=yes +else + ac_cv_lib_nsl_gethostbyname=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 +$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } +if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" +fi + + if test $ac_cv_lib_nsl_gethostbyname = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5 +$as_echo_n "checking for gethostbyname in -lbsd... " >&6; } +if ${ac_cv_lib_bsd_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbsd $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_bsd_gethostbyname=yes +else + ac_cv_lib_bsd_gethostbyname=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5 +$as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; } +if test "x$ac_cv_lib_bsd_gethostbyname" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" +fi + + fi + fi + + # lieder@skyler.mavd.honeywell.com says without -lsocket, + # socket/setsockopt and other routines are undefined under SCO ODT + # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary + # on later versions), says Simon Leinen: it contains gethostby* + # variants that don't use the name server (or something). -lsocket + # must be given before -lnsl if both are needed. We assume that + # if connect needs -lnsl, so does gethostbyname. + ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect" +if test "x$ac_cv_func_connect" = xyes; then : + +fi + + if test $ac_cv_func_connect = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5 +$as_echo_n "checking for connect in -lsocket... " >&6; } +if ${ac_cv_lib_socket_connect+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $X_EXTRA_LIBS $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char connect (); +int +main () +{ +return connect (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_socket_connect=yes +else + ac_cv_lib_socket_connect=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5 +$as_echo "$ac_cv_lib_socket_connect" >&6; } +if test "x$ac_cv_lib_socket_connect" = xyes; then : + X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" +fi + + fi + + # Guillermo Gomez says -lposix is necessary on A/UX. + ac_fn_c_check_func "$LINENO" "remove" "ac_cv_func_remove" +if test "x$ac_cv_func_remove" = xyes; then : + +fi + + if test $ac_cv_func_remove = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5 +$as_echo_n "checking for remove in -lposix... " >&6; } +if ${ac_cv_lib_posix_remove+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lposix $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char remove (); +int +main () +{ +return remove (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_posix_remove=yes +else + ac_cv_lib_posix_remove=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5 +$as_echo "$ac_cv_lib_posix_remove" >&6; } +if test "x$ac_cv_lib_posix_remove" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" +fi + + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + ac_fn_c_check_func "$LINENO" "shmat" "ac_cv_func_shmat" +if test "x$ac_cv_func_shmat" = xyes; then : + +fi + + if test $ac_cv_func_shmat = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5 +$as_echo_n "checking for shmat in -lipc... " >&6; } +if ${ac_cv_lib_ipc_shmat+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lipc $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shmat (); +int +main () +{ +return shmat (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ipc_shmat=yes +else + ac_cv_lib_ipc_shmat=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5 +$as_echo "$ac_cv_lib_ipc_shmat" >&6; } +if test "x$ac_cv_lib_ipc_shmat" = xyes; then : + X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" +fi + + fi + fi + + # Check for libraries that X11R6 Xt/Xaw programs need. + ac_save_LDFLAGS=$LDFLAGS + test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" + # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to + # check for ICE first), but we must link in the order -lSM -lICE or + # we get undefined symbols. So assume we have SM if we have ICE. + # These have to be linked with before -lX11, unlike the other + # libraries we check for below, so use a different variable. + # John Interrante, Karl Berry + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5 +$as_echo_n "checking for IceConnectionNumber in -lICE... " >&6; } +if ${ac_cv_lib_ICE_IceConnectionNumber+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lICE $X_EXTRA_LIBS $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char IceConnectionNumber (); +int +main () +{ +return IceConnectionNumber (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ICE_IceConnectionNumber=yes +else + ac_cv_lib_ICE_IceConnectionNumber=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 +$as_echo "$ac_cv_lib_ICE_IceConnectionNumber" >&6; } +if test "x$ac_cv_lib_ICE_IceConnectionNumber" = xyes; then : + X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" +fi + + LDFLAGS=$ac_save_LDFLAGS + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 +$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } +if eval \${$as_ac_Header+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$as_ac_Header=yes" +else + eval "$as_ac_Header=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$as_ac_Header + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if ${ac_cv_search_opendir+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_opendir+:} false; then : + break +fi +done +if ${ac_cv_search_opendir+:} false; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if ${ac_cv_search_opendir+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_opendir+:} false; then : + break +fi +done +if ${ac_cv_search_opendir+:} false; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 +$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } +if ${ac_cv_header_time+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_time=yes +else + ac_cv_header_time=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 +$as_echo "$ac_cv_header_time" >&6; } +if test $ac_cv_header_time = yes; then + +$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h + +fi + +for ac_header in fcntl.h langinfo.h limits.h locale.h stdlib.h \ + string.h strings.h sys/time.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +ac_fn_c_check_header_mongrel "$LINENO" "X11/Xaw/Command.h" "ac_cv_header_X11_Xaw_Command_h" "$ac_includes_default" +if test "x$ac_cv_header_X11_Xaw_Command_h" = xyes; then : + HAVE_XAW=yes +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#ifndef __cplusplus + /* Ultrix mips cc rejects this sort of thing. */ + typedef int charset[2]; + const charset cs = { 0, 0 }; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 +$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } +if ${ac_cv_struct_tm+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include + +int +main () +{ +struct tm tm; + int *p = &tm.tm_sec; + return !p; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_struct_tm=time.h +else + ac_cv_struct_tm=sys/time.h +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 +$as_echo "$ac_cv_struct_tm" >&6; } +if test $ac_cv_struct_tm = sys/time.h; then + +$as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5 +$as_echo_n "checking for working alloca.h... " >&6; } +if ${ac_cv_working_alloca_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +char *p = (char *) alloca (2 * sizeof (int)); + if (p) return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_working_alloca_h=yes +else + ac_cv_working_alloca_h=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5 +$as_echo "$ac_cv_working_alloca_h" >&6; } +if test $ac_cv_working_alloca_h = yes; then + +$as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5 +$as_echo_n "checking for alloca... " >&6; } +if ${ac_cv_func_alloca_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# ifdef HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +void *alloca (size_t); +# endif +# endif +# endif +# endif +#endif + +int +main () +{ +char *p = (char *) alloca (1); + if (p) return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_func_alloca_works=yes +else + ac_cv_func_alloca_works=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5 +$as_echo "$ac_cv_func_alloca_works" >&6; } + +if test $ac_cv_func_alloca_works = yes; then + +$as_echo "#define HAVE_ALLOCA 1" >>confdefs.h + +else + # The SVR3 libPW and SVR4 libucb both contain incompatible functions +# that cause trouble. Some versions do not even contain alloca or +# contain a buggy version. If you still want to use their alloca, +# use ar to extract alloca.o from them instead of compiling alloca.c. + +ALLOCA=\${LIBOBJDIR}alloca.$ac_objext + +$as_echo "#define C_ALLOCA 1" >>confdefs.h + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5 +$as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; } +if ${ac_cv_os_cray+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined CRAY && ! defined CRAY2 +webecray +#else +wenotbecray +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "webecray" >/dev/null 2>&1; then : + ac_cv_os_cray=yes +else + ac_cv_os_cray=no +fi +rm -f conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5 +$as_echo "$ac_cv_os_cray" >&6; } +if test $ac_cv_os_cray = yes; then + for ac_func in _getb67 GETB67 getb67; do + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + +cat >>confdefs.h <<_ACEOF +#define CRAY_STACKSEG_END $ac_func +_ACEOF + + break +fi + + done +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5 +$as_echo_n "checking stack direction for C alloca... " >&6; } +if ${ac_cv_c_stack_direction+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_c_stack_direction=0 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +find_stack_direction (int *addr, int depth) +{ + int dir, dummy = 0; + if (! addr) + addr = &dummy; + *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1; + dir = depth ? find_stack_direction (addr, depth - 1) : 0; + return dir + dummy; +} + +int +main (int argc, char **argv) +{ + return find_stack_direction (0, argc + !argv + 20) < 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_stack_direction=1 +else + ac_cv_c_stack_direction=-1 +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5 +$as_echo "$ac_cv_c_stack_direction" >&6; } +cat >>confdefs.h <<_ACEOF +#define STACK_DIRECTION $ac_cv_c_stack_direction +_ACEOF + + +fi + +for ac_header in stdlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 +$as_echo_n "checking for GNU libc compatible malloc... " >&6; } +if ${ac_cv_func_malloc_0_nonnull+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_malloc_0_nonnull=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +# include +#else +char *malloc (); +#endif + +int +main () +{ +return ! malloc (0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_malloc_0_nonnull=yes +else + ac_cv_func_malloc_0_nonnull=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 +$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } +if test $ac_cv_func_malloc_0_nonnull = yes; then : + +$as_echo "#define HAVE_MALLOC 1" >>confdefs.h + +else + $as_echo "#define HAVE_MALLOC 0" >>confdefs.h + + case " $LIBOBJS " in + *" malloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS malloc.$ac_objext" + ;; +esac + + +$as_echo "#define malloc rpl_malloc" >>confdefs.h + +fi + + +for ac_header in stdlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5 +$as_echo_n "checking for GNU libc compatible realloc... " >&6; } +if ${ac_cv_func_realloc_0_nonnull+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_realloc_0_nonnull=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +# include +#else +char *realloc (); +#endif + +int +main () +{ +return ! realloc (0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_realloc_0_nonnull=yes +else + ac_cv_func_realloc_0_nonnull=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5 +$as_echo "$ac_cv_func_realloc_0_nonnull" >&6; } +if test $ac_cv_func_realloc_0_nonnull = yes; then : + +$as_echo "#define HAVE_REALLOC 1" >>confdefs.h + +else + $as_echo "#define HAVE_REALLOC 0" >>confdefs.h + + case " $LIBOBJS " in + *" realloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS realloc.$ac_objext" + ;; +esac + + +$as_echo "#define realloc rpl_realloc" >>confdefs.h + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5 +$as_echo_n "checking for working memcmp... " >&6; } +if ${ac_cv_func_memcmp_working+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_memcmp_working=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Some versions of memcmp are not 8-bit clean. */ + char c0 = '\100', c1 = '\200', c2 = '\201'; + if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) + return 1; + + /* The Next x86 OpenStep bug shows up only when comparing 16 bytes + or more and with at least one buffer not starting on a 4-byte boundary. + William Lewis provided this test program. */ + { + char foo[21]; + char bar[21]; + int i; + for (i = 0; i < 4; i++) + { + char *a = foo + i; + char *b = bar + i; + strcpy (a, "--------01111111"); + strcpy (b, "--------10000000"); + if (memcmp (a, b, 16) >= 0) + return 1; + } + return 0; + } + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_memcmp_working=yes +else + ac_cv_func_memcmp_working=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5 +$as_echo "$ac_cv_func_memcmp_working" >&6; } +test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in + *" memcmp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" + ;; +esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lstat correctly handles trailing slash" >&5 +$as_echo_n "checking whether lstat correctly handles trailing slash... " >&6; } +if ${ac_cv_func_lstat_dereferences_slashed_symlink+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f conftest.sym conftest.file +echo >conftest.file +if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then + if test "$cross_compiling" = yes; then : + ac_cv_func_lstat_dereferences_slashed_symlink=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +struct stat sbuf; + /* Linux will dereference the symlink and fail, as required by POSIX. + That is better in the sense that it means we will not + have to compile and use the lstat wrapper. */ + return lstat ("conftest.sym/", &sbuf) == 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_lstat_dereferences_slashed_symlink=yes +else + ac_cv_func_lstat_dereferences_slashed_symlink=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +else + # If the `ln -s' command failed, then we probably don't even + # have an lstat function. + ac_cv_func_lstat_dereferences_slashed_symlink=no +fi +rm -f conftest.sym conftest.file + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5 +$as_echo "$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; } + +test $ac_cv_func_lstat_dereferences_slashed_symlink = yes && + +cat >>confdefs.h <<_ACEOF +#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 +_ACEOF + + +if test "x$ac_cv_func_lstat_dereferences_slashed_symlink" = xno; then + case " $LIBOBJS " in + *" lstat.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS lstat.$ac_objext" + ;; +esac + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat accepts an empty string" >&5 +$as_echo_n "checking whether stat accepts an empty string... " >&6; } +if ${ac_cv_func_stat_empty_string_bug+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_stat_empty_string_bug=yes +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +struct stat sbuf; + return stat ("", &sbuf) == 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_stat_empty_string_bug=no +else + ac_cv_func_stat_empty_string_bug=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_stat_empty_string_bug" >&5 +$as_echo "$ac_cv_func_stat_empty_string_bug" >&6; } +if test $ac_cv_func_stat_empty_string_bug = yes; then + case " $LIBOBJS " in + *" stat.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS stat.$ac_objext" + ;; +esac + + +cat >>confdefs.h <<_ACEOF +#define HAVE_STAT_EMPTY_STRING_BUG 1 +_ACEOF + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working strcoll" >&5 +$as_echo_n "checking for working strcoll... " >&6; } +if ${ac_cv_func_strcoll_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_strcoll_works=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +return (strcoll ("abc", "def") >= 0 || + strcoll ("ABC", "DEF") >= 0 || + strcoll ("123", "456") >= 0) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_strcoll_works=yes +else + ac_cv_func_strcoll_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_strcoll_works" >&5 +$as_echo "$ac_cv_func_strcoll_works" >&6; } +if test $ac_cv_func_strcoll_works = yes; then + +$as_echo "#define HAVE_STRCOLL 1" >>confdefs.h + +fi + +for ac_func in strftime +do : + ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime" +if test "x$ac_cv_func_strftime" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRFTIME 1 +_ACEOF + +else + # strftime is in -lintl on SCO UNIX. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5 +$as_echo_n "checking for strftime in -lintl... " >&6; } +if ${ac_cv_lib_intl_strftime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char strftime (); +int +main () +{ +return strftime (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_intl_strftime=yes +else + ac_cv_lib_intl_strftime=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5 +$as_echo "$ac_cv_lib_intl_strftime" >&6; } +if test "x$ac_cv_lib_intl_strftime" = xyes; then : + $as_echo "#define HAVE_STRFTIME 1" >>confdefs.h + +LIBS="-lintl $LIBS" +fi + +fi +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working strtod" >&5 +$as_echo_n "checking for working strtod... " >&6; } +if ${ac_cv_func_strtod+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_strtod=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +$ac_includes_default +#ifndef strtod +double strtod (); +#endif +int +main() +{ + { + /* Some versions of Linux strtod mis-parse strings with leading '+'. */ + char *string = " +69"; + char *term; + double value; + value = strtod (string, &term); + if (value != 69 || term != (string + 4)) + return 1; + } + + { + /* Under Solaris 2.4, strtod returns the wrong value for the + terminating character under some conditions. */ + char *string = "NaN"; + char *term; + strtod (string, &term); + if (term != string && *(term - 1) == 0) + return 1; + } + return 0; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_strtod=yes +else + ac_cv_func_strtod=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_strtod" >&5 +$as_echo "$ac_cv_func_strtod" >&6; } +if test $ac_cv_func_strtod = no; then + case " $LIBOBJS " in + *" strtod.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strtod.$ac_objext" + ;; +esac + +ac_fn_c_check_func "$LINENO" "pow" "ac_cv_func_pow" +if test "x$ac_cv_func_pow" = xyes; then : + +fi + +if test $ac_cv_func_pow = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pow in -lm" >&5 +$as_echo_n "checking for pow in -lm... " >&6; } +if ${ac_cv_lib_m_pow+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pow (); +int +main () +{ +return pow (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_pow=yes +else + ac_cv_lib_m_pow=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_pow" >&5 +$as_echo "$ac_cv_lib_m_pow" >&6; } +if test "x$ac_cv_lib_m_pow" = xyes; then : + POW_LIB=-lm +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot find library containing definition of pow" >&5 +$as_echo "$as_me: WARNING: cannot find library containing definition of pow" >&2;} +fi + +fi + +fi + +for ac_func in memmove memset nl_langinfo putenv regcomp setlocale +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in strchr strdup gettimeofday +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + +# Extract the first word of "m17n-db", so it can be a program name with args. +set dummy m17n-db; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_HAVE_M17N_DB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAVE_M17N_DB"; then + ac_cv_prog_HAVE_M17N_DB="$HAVE_M17N_DB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_HAVE_M17N_DB="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +HAVE_M17N_DB=$ac_cv_prog_HAVE_M17N_DB +if test -n "$HAVE_M17N_DB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_M17N_DB" >&5 +$as_echo "$HAVE_M17N_DB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test "x$HAVE_M17N_DB" = "xyes"; then + M17NDIR=`m17n-db` +else + M17NDIR="${datadir}/m17n" +fi + + + +# Check whether --enable-gui was given. +if test "${enable_gui+set}" = set; then : + enableval=$enable_gui; +fi + + + if test x$with_gui != xno; then + WITH_GUI_TRUE= + WITH_GUI_FALSE='#' +else + WITH_GUI_TRUE='#' + WITH_GUI_FALSE= +fi + + +if test x$with_gui != xno; then + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 +$as_echo_n "checking for library containing dlopen... " >&6; } +if ${ac_cv_search_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_dlopen=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_dlopen+:} false; then : + break +fi +done +if ${ac_cv_search_dlopen+:} false; then : + +else + ac_cv_search_dlopen=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 +$as_echo "$ac_cv_search_dlopen" >&6; } +ac_res=$ac_cv_search_dlopen +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +$as_echo "#define HAVE_DLOPEN 1" >>confdefs.h + +fi + + + +M17N_EXT_LIBS= + +# Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_HAVE_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAVE_PKG_CONFIG"; then + ac_cv_prog_HAVE_PKG_CONFIG="$HAVE_PKG_CONFIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_HAVE_PKG_CONFIG="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +HAVE_PKG_CONFIG=$ac_cv_prog_HAVE_PKG_CONFIG +if test -n "$HAVE_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_PKG_CONFIG" >&5 +$as_echo "$HAVE_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test x$HAVE_PKG_CONFIG = xyes; then + HAVE_PKG_CONFIG_TRUE= + HAVE_PKG_CONFIG_FALSE='#' +else + HAVE_PKG_CONFIG_TRUE='#' + HAVE_PKG_CONFIG_FALSE= +fi + + +if test "x$no_x" != "xyes"; then + +$as_echo "#define HAVE_X11 1" >>confdefs.h + + X11_LD_FLAGS="-lXt -lX11" + M17N_EXT_LIBS="$M17N_EXT_LIBS X11" + + if test "x$HAVE_XAW" = "xyes"; then + +$as_echo "#define HAVE_X11_XAW_COMMAND_H 1" >>confdefs.h + + XAW_LD_FLAGS="-lXaw -lXmu" + CONFIG_FLAGS="$CONFIG_FLAGS -DHAVE_X11_XAW_COMMAND_H" + M17N_EXT_LIBS="$M17N_EXT_LIBS Xaw" + fi +fi + + + +save_CPPFLAGS="$CPPFLAGS" +save_LIBS="$LIBS" +# Extract the first word of "fribidi-config", so it can be a program name with args. +set dummy fribidi-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_HAVE_FRIBIDI_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAVE_FRIBIDI_CONFIG"; then + ac_cv_prog_HAVE_FRIBIDI_CONFIG="$HAVE_FRIBIDI_CONFIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_HAVE_FRIBIDI_CONFIG="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +HAVE_FRIBIDI_CONFIG=$ac_cv_prog_HAVE_FRIBIDI_CONFIG +if test -n "$HAVE_FRIBIDI_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_FRIBIDI_CONFIG" >&5 +$as_echo "$HAVE_FRIBIDI_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test "x$HAVE_FRIBIDI_CONFIG" = "xyes"; then + CPPFLAGS="$CPPFLAGS `fribidi-config --cflags`" + FRIBIDI_LD_FLAGS="`fribidi-config --libs`" + LIBS="$LIBS $FRIBIDI_LD_FLAGS" +else + FRIBIDI_LD_FLAGS=-lfribidi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fribidi_set_mirroring in -lfribidi" >&5 +$as_echo_n "checking for fribidi_set_mirroring in -lfribidi... " >&6; } +if ${ac_cv_lib_fribidi_fribidi_set_mirroring+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lfribidi $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char fribidi_set_mirroring (); +int +main () +{ +return fribidi_set_mirroring (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_fribidi_fribidi_set_mirroring=yes +else + ac_cv_lib_fribidi_fribidi_set_mirroring=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fribidi_fribidi_set_mirroring" >&5 +$as_echo "$ac_cv_lib_fribidi_fribidi_set_mirroring" >&6; } +if test "x$ac_cv_lib_fribidi_fribidi_set_mirroring" = xyes; then : + HAVE_FRIBIDI=yes +else + HAVE_FRIBIDI=no +fi + +ac_fn_c_check_header_mongrel "$LINENO" "fribidi/fribidi.h" "ac_cv_header_fribidi_fribidi_h" "$ac_includes_default" +if test "x$ac_cv_header_fribidi_fribidi_h" = xyes; then : + +else + HAVE_FRIBIDI=no +fi + + +if test "x$HAVE_FRIBIDI" = "xyes"; then + +$as_echo "#define HAVE_FRIBIDI 1" >>confdefs.h + + M17N_EXT_LIBS="$M17N_EXT_LIBS fribidi" +else + CPPFLAGS="$save_CPPFLAGS" + FRIBIDI_LD_FLAGS= +fi +LIBS="$save_LIBS" + + + +# Check whether --with-libotf was given. +if test "${with_libotf+set}" = set; then : + withval=$with_libotf; +fi + + +if test "x$with_libotf" != "xno"; then + save_CPPFLAGS="$CPPFLAGS" + save_LIBS="$LIBS" + # Extract the first word of "libotf-config", so it can be a program name with args. +set dummy libotf-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_HAVE_OTFLIB_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAVE_OTFLIB_CONFIG"; then + ac_cv_prog_HAVE_OTFLIB_CONFIG="$HAVE_OTFLIB_CONFIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_HAVE_OTFLIB_CONFIG="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +HAVE_OTFLIB_CONFIG=$ac_cv_prog_HAVE_OTFLIB_CONFIG +if test -n "$HAVE_OTFLIB_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_OTFLIB_CONFIG" >&5 +$as_echo "$HAVE_OTFLIB_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + OTF_LD_FLAGS=-lotf + if test "x$HAVE_OTFLIB_CONFIG" = "xyes"; then + CPPFLAGS="$CPPFLAGS `libotf-config --cflags`" + OTF_LD_FLAGS="`libotf-config --libs`" + LIBS="$LIBS $OTF_LD_FLAGS" + elif test "x$HAVE_PKG_CONFIG" = "xyes" ; then + if pkg-config libotf ; then + CPPFLAGS="$CPPFLAGS `pkg-config --cflags libotf`" + OTF_LD_FLAGS="`pkg-config --libs libotf`" + fi + fi + ## We check the availability of OTF_check_features + ## because we need libotf-0.9.4 or the later. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OTF_check_features in -lotf" >&5 +$as_echo_n "checking for OTF_check_features in -lotf... " >&6; } +if ${ac_cv_lib_otf_OTF_check_features+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lotf $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char OTF_check_features (); +int +main () +{ +return OTF_check_features (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_otf_OTF_check_features=yes +else + ac_cv_lib_otf_OTF_check_features=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_otf_OTF_check_features" >&5 +$as_echo "$ac_cv_lib_otf_OTF_check_features" >&6; } +if test "x$ac_cv_lib_otf_OTF_check_features" = xyes; then : + HAVE_OTF=yes +else + HAVE_OTF=no +fi + + ac_fn_c_check_header_mongrel "$LINENO" "otf.h" "ac_cv_header_otf_h" "$ac_includes_default" +if test "x$ac_cv_header_otf_h" = xyes; then : + +else + HAVE_OTF=no +fi + + + if test "x$HAVE_OTF" = "xyes"; then + +$as_echo "#define HAVE_OTF 1" >>confdefs.h + + M17N_EXT_LIBS="$M17N_EXT_LIBS libotf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OTF_drive_gpos2 in -lotf" >&5 +$as_echo_n "checking for OTF_drive_gpos2 in -lotf... " >&6; } +if ${ac_cv_lib_otf_OTF_drive_gpos2+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lotf $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char OTF_drive_gpos2 (); +int +main () +{ +return OTF_drive_gpos2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_otf_OTF_drive_gpos2=yes +else + ac_cv_lib_otf_OTF_drive_gpos2=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_otf_OTF_drive_gpos2" >&5 +$as_echo "$ac_cv_lib_otf_OTF_drive_gpos2" >&6; } +if test "x$ac_cv_lib_otf_OTF_drive_gpos2" = xyes; then : + HAVE_OTF_DRIVE_GPOS2=yes +else + HAVE_OTF_DRIVE_GPOS2=no +fi + + if test "x$HAVE_OTF_DRIVE_GPOS2" = "xyes"; then + +$as_echo "#define HAVE_OTF_DRIVE_GPOS2 1" >>confdefs.h + + fi + else + CPPFLAGS="$save_CPPFLAGS" + OTF_LD_FLAGS= + fi + LIBS="$save_LIBS" +fi + + +# Extract the first word of "freetype-config", so it can be a program name with args. +set dummy freetype-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_HAVE_FREETYPE_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAVE_FREETYPE_CONFIG"; then + ac_cv_prog_HAVE_FREETYPE_CONFIG="$HAVE_FREETYPE_CONFIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_HAVE_FREETYPE_CONFIG="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +HAVE_FREETYPE_CONFIG=$ac_cv_prog_HAVE_FREETYPE_CONFIG +if test -n "$HAVE_FREETYPE_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_FREETYPE_CONFIG" >&5 +$as_echo "$HAVE_FREETYPE_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test "x$HAVE_FREETYPE_CONFIG" = "xyes"; then + FREETYPE_INC=`freetype-config --cflags` + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $FREETYPE_INC" + ac_fn_c_check_header_mongrel "$LINENO" "ft2build.h" "ac_cv_header_ft2build_h" "$ac_includes_default" +if test "x$ac_cv_header_ft2build_h" = xyes; then : + HAVE_FREETYPE=yes +else + HAVE_FREETYPE=no CPPFLAGS="$save_CPPFLAGS" +fi + + + if test "x$HAVE_FREETYPE" = "xyes" ; then + save_LIBS="$LIBS" + LIBS="$LIBS `freetype-config --libs`" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FT_Init_FreeType in -lfreetype" >&5 +$as_echo_n "checking for FT_Init_FreeType in -lfreetype... " >&6; } +if ${ac_cv_lib_freetype_FT_Init_FreeType+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lfreetype $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char FT_Init_FreeType (); +int +main () +{ +return FT_Init_FreeType (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_freetype_FT_Init_FreeType=yes +else + ac_cv_lib_freetype_FT_Init_FreeType=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_freetype_FT_Init_FreeType" >&5 +$as_echo "$ac_cv_lib_freetype_FT_Init_FreeType" >&6; } +if test "x$ac_cv_lib_freetype_FT_Init_FreeType" = xyes; then : + HAVE_FREETYPE=yes +else + HAVE_FREETYPE=no +fi + + LIBS="$save_LIBS" + if test "x$HAVE_FREETYPE" = "xyes"; then + FREETYPE_LD_FLAGS=`freetype-config --libs` + +$as_echo "#define HAVE_FREETYPE 1" >>confdefs.h + + M17N_EXT_LIBS="$M17N_EXT_LIBS freetype" + ac_fn_c_check_header_compile "$LINENO" "freetype/ftbdf.h" "ac_cv_header_freetype_ftbdf_h" "#include +#include FT_FREETYPE_H +" +if test "x$ac_cv_header_freetype_ftbdf_h" = xyes; then : + HAVE_FTBDF_H=yes +else + HAVE_FTBDF_H=no +fi + + + if test "x$HAVE_FTBDF_H" = "xyes"; then + +$as_echo "#define HAVE_FTBDF_H 1" >>confdefs.h + + fi + CONFIG_FLAGS="$CONFIG_FLAGS -DHAVE_FREETYPE" + fi + fi +fi + + +save_CPPFLAGS="$CPPFLAGS" +save_LIBS="$LIBS" +XFT2_LD_FLAGS="-lXft -lfreetype -lfontconfig -lXrender -lX11" +# Extract the first word of "xft-config", so it can be a program name with args. +set dummy xft-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_HAVE_XFT_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAVE_XFT_CONFIG"; then + ac_cv_prog_HAVE_XFT_CONFIG="$HAVE_XFT_CONFIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_HAVE_XFT_CONFIG="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +HAVE_XFT_CONFIG=$ac_cv_prog_HAVE_XFT_CONFIG +if test -n "$HAVE_XFT_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_XFT_CONFIG" >&5 +$as_echo "$HAVE_XFT_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test "x$HAVE_XFT_CONFIG" = "xyes"; then + CPPFLAGS="$CPPFLAGS `xft-config --cflags`" + XFT2_LD_FLAGS="`xft-config --libs`" +elif test "x$HAVE_PKG_CONFIG" = "xyes" ; then + if pkg-config xft ; then + CPPFLAGS="$CPPFLAGS `pkg-config --cflags xft`" + XFT2_LD_FLAGS="`pkg-config --libs xft`" + fi +fi +LIBS="$LIBS $XFT2_LD_FLAGS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XftDrawCreate in -lXft" >&5 +$as_echo_n "checking for XftDrawCreate in -lXft... " >&6; } +if ${ac_cv_lib_Xft_XftDrawCreate+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXft $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XftDrawCreate (); +int +main () +{ +return XftDrawCreate (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_Xft_XftDrawCreate=yes +else + ac_cv_lib_Xft_XftDrawCreate=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xft_XftDrawCreate" >&5 +$as_echo "$ac_cv_lib_Xft_XftDrawCreate" >&6; } +if test "x$ac_cv_lib_Xft_XftDrawCreate" = xyes; then : + HAVE_XFT2=yes +else + HAVE_XFT2=no +fi + +ac_fn_c_check_header_compile "$LINENO" "X11/Xft/Xft.h" "ac_cv_header_X11_Xft_Xft_h" "#include +#if XftVersion >= 20000 +#else +Version too old. Compiling this line should fail. +#endif +" +if test "x$ac_cv_header_X11_Xft_Xft_h" = xyes; then : + +else + HAVE_XFT2=no +fi + + +if test "x$HAVE_XFT2" = "xyes"; then + +$as_echo "#define HAVE_XFT2 1" >>confdefs.h + + M17N_EXT_LIBS="$M17N_EXT_LIBS xft2" +else + XFT2_LD_FLAGS= + CPPFLAGS="$save_CPPFLAGS" +fi +LIBS="$save_LIBS" + + + +# Check whether --with-fontconfig was given. +if test "${with_fontconfig+set}" = set; then : + withval=$with_fontconfig; +fi + +if test "x$with_fontconfig" != "xno"; then + save_CPPFLAGS="$CPPFLAGS" + save_LIBS="$LIBS" + FONTCONFIG_LD_FLAGS=-lfontconfig + if test "x$HAVE_PKG_CONFIG" = "xyes"; then + if pkg-config --exists fontconfig; then + CPPFLAGS="$CPPFLAGS `pkg-config --cflags fontconfig`" + FONTCONFIG_LD_FLAGS="`pkg-config --libs fontconfig`" + LIBS="$LIBS $FONTCONFIG_LD_FLAGS" + fi + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FcInit in -lfontconfig" >&5 +$as_echo_n "checking for FcInit in -lfontconfig... " >&6; } +if ${ac_cv_lib_fontconfig_FcInit+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lfontconfig $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char FcInit (); +int +main () +{ +return FcInit (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_fontconfig_FcInit=yes +else + ac_cv_lib_fontconfig_FcInit=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fontconfig_FcInit" >&5 +$as_echo "$ac_cv_lib_fontconfig_FcInit" >&6; } +if test "x$ac_cv_lib_fontconfig_FcInit" = xyes; then : + HAVE_FONTCONFIG=yes +else + HAVE_FONTCONFIG=no +fi + + ac_fn_c_check_header_mongrel "$LINENO" "fontconfig/fontconfig.h" "ac_cv_header_fontconfig_fontconfig_h" "$ac_includes_default" +if test "x$ac_cv_header_fontconfig_fontconfig_h" = xyes; then : + +else + HAVE_FONTCONFIG=no +fi + + + if test "x$HAVE_FONTCONFIG" = "xyes"; then + +$as_echo "#define HAVE_FONTCONFIG 1" >>confdefs.h + + M17N_EXT_LIBS="$M17N_EXT_LIBS fontconfig" + else + FONTCONFIG_LD_FLAGS= + CPPFLAGS="$save_CPPFLAGS" + fi + LIBS="$save_LIBS" +fi + + + +# Check whether --with-gd was given. +if test "${with_gd+set}" = set; then : + withval=$with_gd; +fi + + +if test "x$with_gd" != "xno"; then + save_LIBS="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdImageCreate in -lgd" >&5 +$as_echo_n "checking for gdImageCreate in -lgd... " >&6; } +if ${ac_cv_lib_gd_gdImageCreate+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgd $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gdImageCreate (); +int +main () +{ +return gdImageCreate (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_gd_gdImageCreate=yes +else + ac_cv_lib_gd_gdImageCreate=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gd_gdImageCreate" >&5 +$as_echo "$ac_cv_lib_gd_gdImageCreate" >&6; } +if test "x$ac_cv_lib_gd_gdImageCreate" = xyes; then : + HAVE_GD=yes +else + HAVE_GD=no +fi + + ac_fn_c_check_header_mongrel "$LINENO" "gd.h" "ac_cv_header_gd_h" "$ac_includes_default" +if test "x$ac_cv_header_gd_h" = xyes; then : + +else + HAVE_GD=no +fi + + + if test "x$HAVE_GD" = "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdImageCreateTrueColor in -lgd" >&5 +$as_echo_n "checking for gdImageCreateTrueColor in -lgd... " >&6; } +if ${ac_cv_lib_gd_gdImageCreateTrueColor+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgd $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gdImageCreateTrueColor (); +int +main () +{ +return gdImageCreateTrueColor (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_gd_gdImageCreateTrueColor=yes +else + ac_cv_lib_gd_gdImageCreateTrueColor=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gd_gdImageCreateTrueColor" >&5 +$as_echo "$ac_cv_lib_gd_gdImageCreateTrueColor" >&6; } +if test "x$ac_cv_lib_gd_gdImageCreateTrueColor" = xyes; then : + HAVE_GD=2 +else + HAVE_GD=1 +fi + + +cat >>confdefs.h <<_ACEOF +#define HAVE_GD $HAVE_GD +_ACEOF + + M17N_EXT_LIBS="$M17N_EXT_LIBS gdlib" + GD_LD_FLAGS=-lgd + CONFIG_FLAGS="$CONFIG_FLAGS -DHAVE_GD=$HAVE_GD" + fi + LIBS="$save_LIBS" +fi + + +fi + +save_CPPFLAGS="$CPPFLAGS" +save_LIBS="$LIBS" +# Extract the first word of "xml2-config", so it can be a program name with args. +set dummy xml2-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_HAVE_XML2_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAVE_XML2_CONFIG"; then + ac_cv_prog_HAVE_XML2_CONFIG="$HAVE_XML2_CONFIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_HAVE_XML2_CONFIG="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +HAVE_XML2_CONFIG=$ac_cv_prog_HAVE_XML2_CONFIG +if test -n "$HAVE_XML2_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_XML2_CONFIG" >&5 +$as_echo "$HAVE_XML2_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test "x$HAVE_XML2_CONFIG" = "xyes"; then + CPPFLAGS="$CPPFLAGS `xml2-config --cflags`" + XML2_LD_FLAGS="`xml2-config --libs`" + LIBS="$LIBS $XML2_LD_FLAGS" +else + CPPFLAGS="$CPPFLAGS -I/usr/include/libxml2" + XML2_LD_FLAGS="-lxml2 -lz -lpthread -lm" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlParseMemory in -lxml2" >&5 +$as_echo_n "checking for xmlParseMemory in -lxml2... " >&6; } +if ${ac_cv_lib_xml2_xmlParseMemory+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lxml2 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char xmlParseMemory (); +int +main () +{ +return xmlParseMemory (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_xml2_xmlParseMemory=yes +else + ac_cv_lib_xml2_xmlParseMemory=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xml2_xmlParseMemory" >&5 +$as_echo "$ac_cv_lib_xml2_xmlParseMemory" >&6; } +if test "x$ac_cv_lib_xml2_xmlParseMemory" = xyes; then : + HAVE_XML2=yes +else + HAVE_XML2=no +fi + +ac_fn_c_check_header_compile "$LINENO" "libxml/tree.h" "ac_cv_header_libxml_tree_h" "/**/ +" +if test "x$ac_cv_header_libxml_tree_h" = xyes; then : + +else + HAVE_XML2=no +fi + + +if test "x$HAVE_XML2" = "xyes"; then + +$as_echo "#define HAVE_XML2 1" >>confdefs.h + + M17N_EXT_LIBS="$M17N_EXT_LIBS xml2" +else + XML2_LD_FLAGS= + CPPFLAGS="$save_CPPFLAGS" +fi +LIBS="$save_LIBS" + + + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANTHY" >&5 +$as_echo_n "checking for ANTHY... " >&6; } + +if test -n "$ANTHY_CFLAGS"; then + pkg_cv_ANTHY_CFLAGS="$ANTHY_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"anthy\""; } >&5 + ($PKG_CONFIG --exists --print-errors "anthy") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_ANTHY_CFLAGS=`$PKG_CONFIG --cflags "anthy" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$ANTHY_LIBS"; then + pkg_cv_ANTHY_LIBS="$ANTHY_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"anthy\""; } >&5 + ($PKG_CONFIG --exists --print-errors "anthy") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_ANTHY_LIBS=`$PKG_CONFIG --libs "anthy" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + ANTHY_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "anthy" 2>&1` + else + ANTHY_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "anthy" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$ANTHY_PKG_ERRORS" >&5 + + HAVE_ANTHY=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + HAVE_ANTHY=no +else + ANTHY_CFLAGS=$pkg_cv_ANTHY_CFLAGS + ANTHY_LIBS=$pkg_cv_ANTHY_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + HAVE_ANTHY=yes +fi +if test "x$HAVE_ANTHY" = "xyes"; then + +$as_echo "#define HAVE_ANTHY 1" >>confdefs.h + + M17N_EXT_LIBS="$M17N_EXT_LIBS anthy" + ANTHY_LD_FLAGS="$ANTHY_LIBS" + CONFIG_FLAGS="$CONFIG_FLAGS -DHAVE_ANTHY" +fi + + +# Extract the first word of "ispell", so it can be a program name with args. +set dummy ispell; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_HAVE_ISPELL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$HAVE_ISPELL"; then + ac_cv_prog_HAVE_ISPELL="$HAVE_ISPELL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_HAVE_ISPELL="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +HAVE_ISPELL=$ac_cv_prog_HAVE_ISPELL +if test -n "$HAVE_ISPELL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_ISPELL" >&5 +$as_echo "$HAVE_ISPELL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test "x$HAVE_ISPELL" = "xyes"; then + +$as_echo "#define HAVE_ISPELL 1" >>confdefs.h + + M17N_EXT_LIBS="$M17N_EXT_LIBS ispell" + CONFIG_FLAGS="$CONFIG_FLAGS -DHAVE_ISPELL" +fi + + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBTHAI" >&5 +$as_echo_n "checking for LIBTHAI... " >&6; } + +if test -n "$LIBTHAI_CFLAGS"; then + pkg_cv_LIBTHAI_CFLAGS="$LIBTHAI_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libthai\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libthai") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBTHAI_CFLAGS=`$PKG_CONFIG --cflags "libthai" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBTHAI_LIBS"; then + pkg_cv_LIBTHAI_LIBS="$LIBTHAI_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libthai\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libthai") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBTHAI_LIBS=`$PKG_CONFIG --libs "libthai" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBTHAI_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libthai" 2>&1` + else + LIBTHAI_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libthai" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBTHAI_PKG_ERRORS" >&5 + + HAVE_LIBTHAI=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + HAVE_LIBTHAI=no +else + LIBTHAI_CFLAGS=$pkg_cv_LIBTHAI_CFLAGS + LIBTHAI_LIBS=$pkg_cv_LIBTHAI_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + HAVE_LIBTHAI=yes +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for WORDCUT" >&5 +$as_echo_n "checking for WORDCUT... " >&6; } + +if test -n "$WORDCUT_CFLAGS"; then + pkg_cv_WORDCUT_CFLAGS="$WORDCUT_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"wordcut\""; } >&5 + ($PKG_CONFIG --exists --print-errors "wordcut") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_WORDCUT_CFLAGS=`$PKG_CONFIG --cflags "wordcut" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$WORDCUT_LIBS"; then + pkg_cv_WORDCUT_LIBS="$WORDCUT_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"wordcut\""; } >&5 + ($PKG_CONFIG --exists --print-errors "wordcut") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_WORDCUT_LIBS=`$PKG_CONFIG --libs "wordcut" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + WORDCUT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "wordcut" 2>&1` + else + WORDCUT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "wordcut" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$WORDCUT_PKG_ERRORS" >&5 + + HAVE_WORDCUT=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + HAVE_WORDCUT=no +else + WORDCUT_CFLAGS=$pkg_cv_WORDCUT_CFLAGS + WORDCUT_LIBS=$pkg_cv_WORDCUT_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + HAVE_WORDCUT=yes +fi + +if test "x$HAVE_LIBTHAI" == "xyes"; then + + +$as_echo "#define HAVE_LIBTHAI 1" >>confdefs.h + + THAI_WORDSEG_LD_FLAGS="$LIBTHAI_LIBS" + M17N_EXT_LIBS="$M17N_EXT_LIBS libthai" + HAVE_THAI_WORDSEG=yes + +elif test "x$HAVE_WORDCUT" = "xyes"; then + + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $WORDCUT_CFLAGS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + HAVE_WORDCUT=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext + if test "x$HAVE_WORDCUT" = "xno"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB_2_0" >&5 +$as_echo_n "checking for GLIB_2_0... " >&6; } + +if test -n "$GLIB_2_0_CFLAGS"; then + pkg_cv_GLIB_2_0_CFLAGS="$GLIB_2_0_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLIB_2_0_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GLIB_2_0_LIBS"; then + pkg_cv_GLIB_2_0_LIBS="$GLIB_2_0_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLIB_2_0_LIBS=`$PKG_CONFIG --libs "glib-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GLIB_2_0_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0" 2>&1` + else + GLIB_2_0_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GLIB_2_0_PKG_ERRORS" >&5 + + HAVE_GLIB_2_0=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + HAVE_GLIB_2_0=no +else + GLIB_2_0_CFLAGS=$pkg_cv_GLIB_2_0_CFLAGS + GLIB_2_0_LIBS=$pkg_cv_GLIB_2_0_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + HAVE_GLIB_2_0=yes +fi + if test "x$HAVE_GLIB_2_0" = "xyes"; then + CPPFLAGS="$CPPFLAGS $GLIB_2_0_CFLAGS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + HAVE_WORDCUT=yes +fi +rm -f conftest.err conftest.i conftest.$ac_ext + fi + fi + if test "x$HAVE_WORDCUT" = "xyes"; then + THAI_WORDSEG_LD_FLAGS="$WORDCUT_LIBS" + +$as_echo "#define HAVE_WORDCUT 1" >>confdefs.h + + M17N_EXT_LIBS="$M17N_EXT_LIBS wordcut" + HAVE_THAI_WORDSEG=yes + else + CPPFLAGS="$save_CPPFLAGS" + fi + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wordcut_init in -lwordcut" >&5 +$as_echo_n "checking for wordcut_init in -lwordcut... " >&6; } +if ${ac_cv_lib_wordcut_wordcut_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lwordcut $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char wordcut_init (); +int +main () +{ +return wordcut_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_wordcut_wordcut_init=yes +else + ac_cv_lib_wordcut_wordcut_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_wordcut_wordcut_init" >&5 +$as_echo "$ac_cv_lib_wordcut_wordcut_init" >&6; } +if test "x$ac_cv_lib_wordcut_wordcut_init" = xyes; then : + HAVE_WORDCUT_OLD=yes +fi + + if test "x$HAVE_WORDCUT_OLD" = "xyes"; then + if test -f "/usr/share/wordcut/tdict.wcd"; then + tdict="/usr/share/wordcut/tdict.wcd" + elif test -f "/usr/local/share/wordcut/tdict.wcd"; then + tdict="/usr/local/share/wordcut/tdict.wcd" + fi + echo "TDICT=$tdict" + if test "x$tdict" != "x"; then + +$as_echo "#define HAVE_WORDCUT_OLD 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define WORDCUT_TDICT "$tdict" +_ACEOF + + THAI_WORDSEG_LD_FLAGS=-lwordcut + M17N_EXT_LIBS="$M17N_EXT_LIBS wordcut-old" + HAVE_THAI_WORDSEG=yes + else + HAVE_WORDCUT=no + fi + fi +fi + +if test "x$HAVE_THAI_WORDSEG" = "xyes"; then + +$as_echo "#define HAVE_THAI_WORDSEG 1" >>confdefs.h + +fi + + + + + +CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + +SHLIB_EXT=".so" +case $host_os in +darwin* | rhapsody*) + SHLIB_EXT=".dylib";; +esac + +cat >>confdefs.h <<_ACEOF +#define DLOPEN_SHLIB_EXT "$SHLIB_EXT" +_ACEOF + + +ac_config_files="$ac_config_files Makefile intl/Makefile po/Makefile.in src/Makefile example/Makefile m17n-config m17n-core.pc m17n-shell.pc m17n-flt.pc m17n-gui.pc" + + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +if test -z "${WITH_GUI_TRUE}" && test -z "${WITH_GUI_FALSE}"; then + as_fn_error $? "conditional \"WITH_GUI\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_PKG_CONFIG_TRUE}" && test -z "${HAVE_PKG_CONFIG_FALSE}"; then + as_fn_error $? "conditional \"HAVE_PKG_CONFIG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by m17n-lib $as_me 1.8.0, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +m17n-lib config.status 1.8.0 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" +# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake < 1.5. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +PATH_SEPARATOR \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_cv_nm_interface \ +nm_file_list_spec \ +lt_cv_truncate_bin \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' + +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "po-directories") CONFIG_COMMANDS="$CONFIG_COMMANDS po-directories" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "intl/Makefile") CONFIG_FILES="$CONFIG_FILES intl/Makefile" ;; + "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "example/Makefile") CONFIG_FILES="$CONFIG_FILES example/Makefile" ;; + "m17n-config") CONFIG_FILES="$CONFIG_FILES m17n-config" ;; + "m17n-core.pc") CONFIG_FILES="$CONFIG_FILES m17n-core.pc" ;; + "m17n-shell.pc") CONFIG_FILES="$CONFIG_FILES m17n-shell.pc" ;; + "m17n-flt.pc") CONFIG_FILES="$CONFIG_FILES m17n-flt.pc" ;; + "m17n-gui.pc") CONFIG_FILES="$CONFIG_FILES m17n-gui.pc" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "po-directories":C) + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + # Treat a directory as a PO directory if and only if it has a + # POTFILES.in file. This allows packages to have multiple PO + # directories under different names or in different locations. + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assigment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + # Hide the ALL_LINGUAS assigment from automake < 1.5. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + done ;; + "libtool":C) + + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool 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 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool 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, see . + + +# The names of the tagged configurations supported by this script. +available_tags='' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot=$lt_sysroot + +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \$shlibpath_var if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain=$ac_aux_dir/ltmain.sh + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +echo "The m17n library is configured with these external libraries." +echo " $M17N_EXT_LIBS" + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..7f8b08e --- /dev/null +++ b/configure.ac @@ -0,0 +1,476 @@ +dnl configure.ac -- autoconf script for the m17n library. + +dnl Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +dnl National Institute of Advanced Industrial Science and Technology (AIST) +dnl Registration Number H15PRO112 +dnl Copyright (C) 2015, 2016, 2017 K. Handa + +dnl This file is part of the m17n library. + +dnl The m17n library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public License +dnl as published by the Free Software Foundation; either version 2.1 of +dnl the License, or (at your option) any later version. + +dnl The m17n library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. + +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with the m17n library; if not, write to the Free +dnl Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +dnl Boston, MA 02110-1301, USA. + +dnl Process this file with autoconf to produce a configure script. + +AC_INIT([m17n-lib],[1.8.0],[m17n-lib-bug@m17n.org]) +AC_CONFIG_MACRO_DIR([m4]) +AM_INIT_AUTOMAKE +AC_CONFIG_HEADERS([config.h]) +AM_MAINTAINER_MODE + +API_VERSION=4:2:4 +AC_SUBST(API_VERSION) + +# The earliest version that this release has binary compatibility +# with. This is used for module locations. +M17N_BINARY_VERSION=1.0 + +M17N_MODULE_DIR="m17n/$M17N_BINARY_VERSION" +AC_SUBST(M17N_MODULE_DIR) + + +dnl Checks for programs for compiling. +AC_PROG_CC +AC_GNU_SOURCE + +AM_GNU_GETTEXT +AM_GNU_GETTEXT_VERSION([0.17]) +GETTEXTDIR="$datadir/locale" +AC_SUBST(GETTEXTDIR) + +AC_PROG_LIBTOOL +dnl LT_PREREQ([2.2.4]) +dnl LT_INIT + +dnl Checks for X libraries. +AC_PATH_XTRA + +dnl Checks for standard header files. +AC_HEADER_STDC +AC_HEADER_DIRENT +AC_HEADER_TIME +AC_CHECK_HEADERS([fcntl.h langinfo.h limits.h locale.h stdlib.h \ + string.h strings.h sys/time.h unistd.h]) +AC_CHECK_HEADER(X11/Xaw/Command.h, HAVE_XAW=yes) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_INLINE +AC_TYPE_SIZE_T +AC_STRUCT_TM + +dnl Checks for endian. This influence the default UTF-16 definition. +AC_C_BIGENDIAN + +dnl Checks for library functions. +AC_FUNC_ALLOCA +AC_FUNC_MALLOC +AC_FUNC_REALLOC +AC_FUNC_MEMCMP +AC_FUNC_STAT +AC_FUNC_STRCOLL +AC_FUNC_STRFTIME +AC_FUNC_STRTOD +AC_CHECK_FUNCS(memmove memset nl_langinfo putenv regcomp setlocale) +AC_CHECK_FUNCS(strchr strdup gettimeofday) + +dnl Checks where the m17n database is installed. + +AC_CHECK_PROG(HAVE_M17N_DB, m17n-db, yes) +if test "x$HAVE_M17N_DB" = "xyes"; then + M17NDIR=`m17n-db` +else + M17NDIR="${datadir}/m17n" +fi +AC_SUBST(M17NDIR) + +dnl Checks which levels of APIs should be compiled. + +AC_ARG_ENABLE(gui, + AS_HELP_STRING([--enable-gui],[enable GUI level APIs (default is YES)])) + +AM_CONDITIONAL(WITH_GUI, test x$with_gui != xno) + +if test x$with_gui != xno; then + +dnl Checks if dlopen exists, and if it's in libc or libdl. + +AC_SEARCH_LIBS(dlopen, dl, + AC_DEFINE(HAVE_DLOPEN, 1, + [Define to 1 if you have the function dlopen.])) + +dnl Check several libraries without adding -lxxx to LIBS, without +dnl defining HAVE_LIBXXX nor HAVE_XXX_H because they are used only by +dnl some libraries (e.g. libm17n-X.so). Instead, define XXX_LD_FLAGS +dnl and HAVE_XXX if library XXX is available. CPPFLAGS will be +dnl augmented. + +M17N_EXT_LIBS= + +AC_CHECK_PROG(HAVE_PKG_CONFIG, pkg-config, yes) +AM_CONDITIONAL([HAVE_PKG_CONFIG], [test x$HAVE_PKG_CONFIG = xyes]) + +if test "x$no_x" != "xyes"; then + AC_DEFINE(HAVE_X11, 1, [Define to 1 if you have X11.]) + X11_LD_FLAGS="-lXt -lX11" + M17N_EXT_LIBS="$M17N_EXT_LIBS X11" + + if test "x$HAVE_XAW" = "xyes"; then + AC_DEFINE(HAVE_X11_XAW_COMMAND_H, 1, + [Define to 1 if you have the Xaw header files.]) + XAW_LD_FLAGS="-lXaw -lXmu" + CONFIG_FLAGS="$CONFIG_FLAGS -DHAVE_X11_XAW_COMMAND_H" + M17N_EXT_LIBS="$M17N_EXT_LIBS Xaw" + fi +fi +AC_SUBST(X11_LD_FLAGS) +AC_SUBST(XAW_LD_FLAGS) + +dnl Check for fribidi library. +save_CPPFLAGS="$CPPFLAGS" +save_LIBS="$LIBS" +AC_CHECK_PROG(HAVE_FRIBIDI_CONFIG, fribidi-config, yes) +if test "x$HAVE_FRIBIDI_CONFIG" = "xyes"; then + CPPFLAGS="$CPPFLAGS `fribidi-config --cflags`" + FRIBIDI_LD_FLAGS="`fribidi-config --libs`" + LIBS="$LIBS $FRIBIDI_LD_FLAGS" +else + FRIBIDI_LD_FLAGS=-lfribidi +fi +AC_CHECK_LIB(fribidi, fribidi_set_mirroring, HAVE_FRIBIDI=yes, HAVE_FRIBIDI=no) +AC_CHECK_HEADER(fribidi/fribidi.h,, HAVE_FRIBIDI=no) +if test "x$HAVE_FRIBIDI" = "xyes"; then + AC_DEFINE(HAVE_FRIBIDI, 1, + [Define to 1 if you have Fribidi library and header file.]) + M17N_EXT_LIBS="$M17N_EXT_LIBS fribidi" +else + CPPFLAGS="$save_CPPFLAGS" + FRIBIDI_LD_FLAGS= +fi +LIBS="$save_LIBS" +AC_SUBST(FRIBIDI_LD_FLAGS) + +dnl Check for otflib usability. +AC_ARG_WITH(libotf, + AS_HELP_STRING([--with-libotf],[with OpenType font suport (default is YES)])) + +if test "x$with_libotf" != "xno"; then + save_CPPFLAGS="$CPPFLAGS" + save_LIBS="$LIBS" + AC_CHECK_PROG(HAVE_OTFLIB_CONFIG, libotf-config, yes) + OTF_LD_FLAGS=-lotf + if test "x$HAVE_OTFLIB_CONFIG" = "xyes"; then + CPPFLAGS="$CPPFLAGS `libotf-config --cflags`" + OTF_LD_FLAGS="`libotf-config --libs`" + LIBS="$LIBS $OTF_LD_FLAGS" + elif test "x$HAVE_PKG_CONFIG" = "xyes" ; then + if pkg-config libotf ; then + CPPFLAGS="$CPPFLAGS `pkg-config --cflags libotf`" + OTF_LD_FLAGS="`pkg-config --libs libotf`" + fi + fi + ## We check the availability of OTF_check_features + ## because we need libotf-0.9.4 or the later. + AC_CHECK_LIB(otf, OTF_check_features, HAVE_OTF=yes, HAVE_OTF=no) + AC_CHECK_HEADER(otf.h,, HAVE_OTF=no) + if test "x$HAVE_OTF" = "xyes"; then + AC_DEFINE(HAVE_OTF, 1, + [Define to 1 if you have OTF library and header file.]) + M17N_EXT_LIBS="$M17N_EXT_LIBS libotf" + AC_CHECK_LIB(otf, OTF_drive_gpos2, HAVE_OTF_DRIVE_GPOS2=yes, + HAVE_OTF_DRIVE_GPOS2=no) + if test "x$HAVE_OTF_DRIVE_GPOS2" = "xyes"; then + AC_DEFINE(HAVE_OTF_DRIVE_GPOS2, 1, + [Define to 1 if the OTF library has OTF_drive_gpos2().]) + fi + else + CPPFLAGS="$save_CPPFLAGS" + OTF_LD_FLAGS= + fi + LIBS="$save_LIBS" +fi +AC_SUBST(OTF_LD_FLAGS) + +dnl Check for Freetype2 usability. +AC_CHECK_PROG(HAVE_FREETYPE_CONFIG, freetype-config, yes) +if test "x$HAVE_FREETYPE_CONFIG" = "xyes"; then + FREETYPE_INC=`freetype-config --cflags` + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $FREETYPE_INC" + AC_CHECK_HEADER(ft2build.h, HAVE_FREETYPE=yes, + HAVE_FREETYPE=no CPPFLAGS="$save_CPPFLAGS") + if test "x$HAVE_FREETYPE" = "xyes" ; then + save_LIBS="$LIBS" + LIBS="$LIBS `freetype-config --libs`" + AC_CHECK_LIB(freetype, FT_Init_FreeType, HAVE_FREETYPE=yes, + HAVE_FREETYPE=no) + LIBS="$save_LIBS" + if test "x$HAVE_FREETYPE" = "xyes"; then + FREETYPE_LD_FLAGS=`freetype-config --libs` + AC_DEFINE(HAVE_FREETYPE, 1, + [Define to 1 if you have FreeType library and header file.]) + M17N_EXT_LIBS="$M17N_EXT_LIBS freetype" + AC_CHECK_HEADER(freetype/ftbdf.h, HAVE_FTBDF_H=yes, HAVE_FTBDF_H=no, + [#include +#include FT_FREETYPE_H]) + if test "x$HAVE_FTBDF_H" = "xyes"; then + AC_DEFINE(HAVE_FTBDF_H, 1, + [Define to 1 if you have freetype/ftbdf.h.]) + fi + CONFIG_FLAGS="$CONFIG_FLAGS -DHAVE_FREETYPE" + fi + fi +fi +AC_SUBST(FREETYPE_LD_FLAGS) + +dnl Check for Xft2 usability. +save_CPPFLAGS="$CPPFLAGS" +save_LIBS="$LIBS" +XFT2_LD_FLAGS="-lXft -lfreetype -lfontconfig -lXrender -lX11" +AC_CHECK_PROG(HAVE_XFT_CONFIG, xft-config, yes) +if test "x$HAVE_XFT_CONFIG" = "xyes"; then + CPPFLAGS="$CPPFLAGS `xft-config --cflags`" + XFT2_LD_FLAGS="`xft-config --libs`" +elif test "x$HAVE_PKG_CONFIG" = "xyes" ; then + if pkg-config xft ; then + CPPFLAGS="$CPPFLAGS `pkg-config --cflags xft`" + XFT2_LD_FLAGS="`pkg-config --libs xft`" + fi +fi +LIBS="$LIBS $XFT2_LD_FLAGS" +AC_CHECK_LIB(Xft, XftDrawCreate, HAVE_XFT2=yes, HAVE_XFT2=no) +AC_CHECK_HEADER(X11/Xft/Xft.h,, HAVE_XFT2=no, + [#include +#if XftVersion >= 20000 +#else +Version too old. Compiling this line should fail. +#endif]) +if test "x$HAVE_XFT2" = "xyes"; then + AC_DEFINE(HAVE_XFT2, 1, + [Define to 1 if you have Xft2 library and header file.]) + M17N_EXT_LIBS="$M17N_EXT_LIBS xft2" +else + XFT2_LD_FLAGS= + CPPFLAGS="$save_CPPFLAGS" +fi +LIBS="$save_LIBS" +AC_SUBST(XFT2_LD_FLAGS) + +dnl Check for fontconfig usability. +AC_ARG_WITH(fontconfig, + AS_HELP_STRING([--with-fontconfig],[with FontConfig library (default is YES)])) +if test "x$with_fontconfig" != "xno"; then + save_CPPFLAGS="$CPPFLAGS" + save_LIBS="$LIBS" + FONTCONFIG_LD_FLAGS=-lfontconfig + if test "x$HAVE_PKG_CONFIG" = "xyes"; then + if pkg-config --exists fontconfig; then + CPPFLAGS="$CPPFLAGS `pkg-config --cflags fontconfig`" + FONTCONFIG_LD_FLAGS="`pkg-config --libs fontconfig`" + LIBS="$LIBS $FONTCONFIG_LD_FLAGS" + fi + fi + AC_CHECK_LIB(fontconfig, FcInit, HAVE_FONTCONFIG=yes, HAVE_FONTCONFIG=no) + AC_CHECK_HEADER(fontconfig/fontconfig.h, , HAVE_FONTCONFIG=no) + if test "x$HAVE_FONTCONFIG" = "xyes"; then + AC_DEFINE(HAVE_FONTCONFIG, 1, + [Define to 1 if you have fontconfig library and header file.]) + M17N_EXT_LIBS="$M17N_EXT_LIBS fontconfig" + else + FONTCONFIG_LD_FLAGS= + CPPFLAGS="$save_CPPFLAGS" + fi + LIBS="$save_LIBS" +fi +AC_SUBST(FONTCONFIG_LD_FLAGS) + +dnl Check for gdlib usability. +AC_ARG_WITH(gd, + AS_HELP_STRING([--with-gd],[suport graphic device by GD library (default is YES)])) + +if test "x$with_gd" != "xno"; then + save_LIBS="$LIBS" + AC_CHECK_LIB(gd, gdImageCreate, HAVE_GD=yes, HAVE_GD=no) + AC_CHECK_HEADER(gd.h, , HAVE_GD=no) + if test "x$HAVE_GD" = "xyes"; then + AC_CHECK_LIB(gd, gdImageCreateTrueColor, HAVE_GD=2, HAVE_GD=1) + AC_DEFINE_UNQUOTED(HAVE_GD, $HAVE_GD, + [Define to 1 or 2 if you have gd library and header file.]) + M17N_EXT_LIBS="$M17N_EXT_LIBS gdlib" + GD_LD_FLAGS=-lgd + CONFIG_FLAGS="$CONFIG_FLAGS -DHAVE_GD=$HAVE_GD" + fi + LIBS="$save_LIBS" +fi +AC_SUBST(GD_LD_FLAGS) + +fi + +dnl Check for libxml2 usability. +save_CPPFLAGS="$CPPFLAGS" +save_LIBS="$LIBS" +AC_CHECK_PROG(HAVE_XML2_CONFIG, xml2-config, yes) +if test "x$HAVE_XML2_CONFIG" = "xyes"; then + CPPFLAGS="$CPPFLAGS `xml2-config --cflags`" + XML2_LD_FLAGS="`xml2-config --libs`" + LIBS="$LIBS $XML2_LD_FLAGS" +else + CPPFLAGS="$CPPFLAGS -I/usr/include/libxml2" + XML2_LD_FLAGS="-lxml2 -lz -lpthread -lm" +fi +AC_CHECK_LIB(xml2, xmlParseMemory, HAVE_XML2=yes, HAVE_XML2=no) +AC_CHECK_HEADER(libxml/tree.h,, HAVE_XML2=no, /**/) +if test "x$HAVE_XML2" = "xyes"; then + AC_DEFINE(HAVE_XML2, 1, + [Define to 1 if you have libxml2 library and header file]) + M17N_EXT_LIBS="$M17N_EXT_LIBS xml2" +else + XML2_LD_FLAGS= + CPPFLAGS="$save_CPPFLAGS" +fi +LIBS="$save_LIBS" +AC_SUBST(XML2_LD_FLAGS) + +dnl Check for Anthy usability. + +PKG_CHECK_MODULES(ANTHY, anthy, HAVE_ANTHY=yes, HAVE_ANTHY=no) +if test "x$HAVE_ANTHY" = "xyes"; then + AC_DEFINE(HAVE_ANTHY, 1, + [Define to 1 if you have Anthy library and header file]) + M17N_EXT_LIBS="$M17N_EXT_LIBS anthy" + ANTHY_LD_FLAGS="$ANTHY_LIBS" + CONFIG_FLAGS="$CONFIG_FLAGS -DHAVE_ANTHY" +fi +AC_SUBST(ANTHY_LD_FLAGS) + +dnl Check for Ispell usability. +AC_CHECK_PROG(HAVE_ISPELL, ispell, yes) +if test "x$HAVE_ISPELL" = "xyes"; then + AC_DEFINE(HAVE_ISPELL, 1, [Define if ispell is available.]) + M17N_EXT_LIBS="$M17N_EXT_LIBS ispell" + CONFIG_FLAGS="$CONFIG_FLAGS -DHAVE_ISPELL" +fi + +dnl Check for Thai word-segmentation library. +dnl If we have one, define HAVE_THAI_WORDSEG and one of these: +dnl HAVE_LIBTHAI, HAVE_WORDCUT, or HAVE_WORDCUT_OLD +dnl In addition, set THAI_WORDSEG_LD_FLAGS to a proper value. + +PKG_CHECK_MODULES(LIBTHAI, libthai, HAVE_LIBTHAI=yes, HAVE_LIBTHAI=no) +PKG_CHECK_MODULES(WORDCUT, wordcut, HAVE_WORDCUT=yes, HAVE_WORDCUT=no) + +if test "x$HAVE_LIBTHAI" == "xyes"; then + + AC_DEFINE(HAVE_LIBTHAI, 1, [Define if you have libthai]) + THAI_WORDSEG_LD_FLAGS="$LIBTHAI_LIBS" + M17N_EXT_LIBS="$M17N_EXT_LIBS libthai" + HAVE_THAI_WORDSEG=yes + +elif test "x$HAVE_WORDCUT" = "xyes"; then + + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $WORDCUT_CFLAGS" + AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])],[],[HAVE_WORDCUT=no]) + if test "x$HAVE_WORDCUT" = "xno"; then + PKG_CHECK_MODULES(GLIB_2_0, glib-2.0, HAVE_GLIB_2_0=yes, HAVE_GLIB_2_0=no) + if test "x$HAVE_GLIB_2_0" = "xyes"; then + CPPFLAGS="$CPPFLAGS $GLIB_2_0_CFLAGS" + AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])],[HAVE_WORDCUT=yes],[]) + fi + fi + if test "x$HAVE_WORDCUT" = "xyes"; then + THAI_WORDSEG_LD_FLAGS="$WORDCUT_LIBS" + AC_DEFINE(HAVE_WORDCUT, 1, + [Define if you have the wordcut library and header file]) + M17N_EXT_LIBS="$M17N_EXT_LIBS wordcut" + HAVE_THAI_WORDSEG=yes + else + CPPFLAGS="$save_CPPFLAGS" + fi + +else + + AC_CHECK_LIB(wordcut, wordcut_init, HAVE_WORDCUT_OLD=yes) + if test "x$HAVE_WORDCUT_OLD" = "xyes"; then + if test -f "/usr/share/wordcut/tdict.wcd"; then + tdict="/usr/share/wordcut/tdict.wcd" + elif test -f "/usr/local/share/wordcut/tdict.wcd"; then + tdict="/usr/local/share/wordcut/tdict.wcd" + fi + echo "TDICT=$tdict" + if test "x$tdict" != "x"; then + AC_DEFINE(HAVE_WORDCUT_OLD, 1, + [Define if you have the old version of wordcut library]) + AC_DEFINE_UNQUOTED(WORDCUT_TDICT, "$tdict", [Define tdict file name]) + THAI_WORDSEG_LD_FLAGS=-lwordcut + M17N_EXT_LIBS="$M17N_EXT_LIBS wordcut-old" + HAVE_THAI_WORDSEG=yes + else + HAVE_WORDCUT=no + fi + fi +fi + +if test "x$HAVE_THAI_WORDSEG" = "xyes"; then + AC_DEFINE(HAVE_THAI_WORDSEG, 1, + [Define if you have some Thai word-segmentation library]) +fi +AC_SUBST(THAI_WORDSEG_LD_FLAGS) + +AC_SUBST(CONFIG_FLAGS) + +dnl We can't include X_CFLAGS in AM_CPPFLAGS because the generated +dnl Makefile put ${AM_CPPFLAGS} before ${CPPFLAGS} and that leads to +dnl inclusion of an incorrect header file. So, append X_CFLAGS to +dnl CPPFLAGS here directly. + +CPPFLAGS="$CPPFLAGS $X_CFLAGS" + +dnl AC_ARG_ENABLE(xom, +dnl [ --enable-xom build and install XOM library.], +dnl XOM="$enableval") + +SHLIB_EXT=".so" +case $host_os in +darwin* | rhapsody*) + SHLIB_EXT=".dylib";; +esac +AC_DEFINE_UNQUOTED(DLOPEN_SHLIB_EXT, "$SHLIB_EXT", + [Define to loadable module extention]) + +AC_CONFIG_FILES([Makefile intl/Makefile po/Makefile.in + src/Makefile + example/Makefile + m17n-config + m17n-core.pc + m17n-shell.pc + m17n-flt.pc + m17n-gui.pc + ]) + +dnl if test "x$XOM" = "xyes"; then +dnl AC_CONFIG_FILES(omM17N/Makefile) +dnl fi + +AC_OUTPUT + +echo "The m17n library is configured with these external libraries." +echo " $M17N_EXT_LIBS" + +dnl Local Variables: +dnl comment-start: "dnl " +dnl comment-end: "" +dnl comment-start-skip: "\\bdnl\\b\\s *" +dnl End: diff --git a/depcomp b/depcomp new file mode 100755 index 0000000..fc98710 --- /dev/null +++ b/depcomp @@ -0,0 +1,791 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2013-05-30.07; # UTC + +# Copyright (C) 1999-2014 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, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The second -e expression handles DOS-style file names with drive + # letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/example/.gdb.util b/example/.gdb.util new file mode 100644 index 0000000..efc3b4b --- /dev/null +++ b/example/.gdb.util @@ -0,0 +1,62 @@ +define xchartab +set mdebug_dump_chartab ($, 0) +echo \n +end + +define xsymbol +set mdebug_dump_symbol ($, 0) +echo \n +end + +define xmtext +set mdebug_dump_mtext ($, 1, 0) +echo \n +end + +define xplist +set mdebug_dump_plist ($, 0) +echo \n +end + +define xinterval +set dump_interval ($arg0, 0) +echo \n +end + +define xfont +set mdebug_dump_font ($) +echo \n +end + +define xfontset +set mdebug_dump_fontset ($, 0) +echo \n +end + +define xface +set mdebug_dump_face ($, 0) +echo \n +end + +define xgstring +set dump_gstring (gstring, 0, 0) +echo \n +end + +define xgstr +set dump_gstring ($arg0, 0, 1) +echo \n +end + +define xim +set mdebug_dump_im ($, 0) +echo \n +end + +define xflush +call XFlush (display) +end + +define xsynch +call XSynchronize (display, 1) +end diff --git a/example/.gdbinit b/example/.gdbinit new file mode 100644 index 0000000..db736ae --- /dev/null +++ b/example/.gdbinit @@ -0,0 +1,23 @@ +set main + +# br mdebug_hook + +source .gdb.util + +set env LD_LIBRARY_PATH=../src/.libs:./.libs:/usr/local/lib + +set env EF_ALLOW_MALLOC_0=1 +set env EF_PROTECT_FREE=1 +set env EF_OVERRUN_DETECTION=1 +set env EF_FREE_WIPES=1 + +set env MDEBUG_INIT=1 +set env MDEBUG_FINI=1 +set env MDEBUG_CHARSET=1 +set env MDEBUG_CODING=1 +set env MDEBUG_DATABASE=1 +set env MDEBUG_FONT=1 +set env MDEBUG_FONT_FLT=0 +set env MDEBUG_FONT_OTF=1 + +set env PURIFYOPTIONS=-chain-length="20" diff --git a/example/ChangeLog b/example/ChangeLog new file mode 100644 index 0000000..5900ffa --- /dev/null +++ b/example/ChangeLog @@ -0,0 +1,821 @@ +2018-02-08 K. Handa + + Version 1.8.0 released. + +2016-01-12 K. Handa + + * Makefile.am (INCLUDES): Delete it. Make this value included in + AM_CPPFLAGS. + +2014-12-10 K. Handa + + * Version 1.7.0 released. + +2014-11-11 K. Handa + + * .gitignore: Converted from .cvsigore. + + * .cvsignore: Delete it. + +2013-06-28 Kenichi Handa + + * mconv.c (main): Fix checking of command line arguments. + +2012-12-15 Kenichi Handa + + * mdump.c (help_exit): Fix typo. + +2012-09-18 Kenichi Handa + + * Version 1.6.4 released. + +2011-10-11 Kenichi Handa + + * Version 1.6.3 released. + +2010-10-05 Kenichi Handa + + * Version 1.6.2 released. + +2010-10-05 Kenichi Handa + + * Makefile.am (INCLUDES): Set -I$(top_srcdir)/src. + +2010-04-23 Kenichi Handa + + * Version 1.6.1 released. + +2010-04-23 Kenichi Handa + + * HELLO.utf8: Add Unicode 5.1 based Myanmar. + +2010-03-30 Kenichi Handa + + * Version 1.6.0 released. + +2010-02-18 Kenichi Handa + + * Makefile.am: Build modules dynamically loaded with + -avoid-version and no -version-info. + +2010-02-09 Kenichi Handa + + * HELLO.utf8 (Greek, Hindi): Fixed. + +2009-08-13 Kenichi Handa + + * Version 1.5.5 released. + +2009-03-02 Kenichi Handa + + * Version 1.5.4 released. + +2009-01-15 Kenichi Handa + + * mconv.c (suppress_warning, continue_on_error): Make them global + variables. + (check_invalid_bytes, check_unencoded_chars): Check + suppress_warning and continue_on_error. + (unknown_encoding): New function. + (FATAL_ERROR): Check suppress_warning. + (main): Use unknown_encoding. Call check_invalid_bytes and + check_unencoded_chars unconditionally. + +2008-12-26 Kenichi Handa + + * mconv.c (main): Print a proper error message if the specified + encoding requires m17n-db. + +2008-10-30 Andreas Schwab (tiny change) + + * medit.c (FilterProc): Fix strict aliasing bug. + +2008-10-30 Kenichi Handa + + * medit.c (update_scroll_bar): Use XawScrollbarSetThumb. + +2008-10-20 Kenichi Handa + + * Version 1.5.3 released. + +2008-06-23 Kenichi Handa + + * Version 1.5.2 released. + + * mview.c: (main): Copyright years updated. + + * mdump.c (main): Copyright years updated. + + * mdate.c: (main): Copyright years updated. + + * medit.c: (main): Copyright years updated. + + * mconv.c (main): Copyright years updated. + +2008-06-13 Kenichi Handa + + * M17NEdit.ja: Shinalese -> Shinhala. + +2008-04-04 Kenichi Handa + + * medit.c (unicode_input_method, saved_input_method): New + variables. + (KeyProc): Make `C-=' activate the unicode input method + temporarily. + (setup_input_methods): Set unicode_input_method if any. + +2008-04-03 Kenichi Handa + + * medit.c (update_cursor): Update control.cursor_pos at first. + +2008-01-31 Kenichi Handa + + * Version 1.5.1 released. + +2008-01-31 Kenichi Handa + + * mview.c: Include . + +2007-12-28 Kenichi Handa + + * Version 1.5.0 released. + +2007-10-29 Kenichi Handa + + * Makefile.am (common_ldflags_gui): Add + ${top_builddir}/src/libm17n-flt.la. + + * .gdb.util (xgstring): Adjusted for the change of dump_gstring. + (xgtr): New command. + +2007-09-18 Kenichi Handa + + * mdump.c (main): Use "generic" fontset by default. + +2007-07-13 Kenichi Handa + + * Version 1.4.0 released. + +2007-05-21 Kenichi Handa + + * medit.c (show_cursor): Use msymbol_name (not mlanguage_name). + +2007-05-16 Kenichi Handa + + * mdate.c (VERSION): Delete it. + (main): Use M17NLIB_VERSION_NAME to print the version number. + + * mconv.c (VERSION): Delete it. + (main): Use M17NLIB_VERSION_NAME to print the version number. + + * mdump.c (PROGRAM_VERSION): Delete it. + (main): Use M17NLIB_VERSION_NAME to print the version number. + + * medit.c (VERSION): Delete it. + (main): Use M17NLIB_VERSION_NAME to print the version number. + + * mview.c (VERSION): Delete it. + (main): Use M17NLIB_VERSION_NAME to print the version number. + +2007-03-29 Kenichi Handa + + * medit.c (setup_input_methods): Use mplist_put_func. + +2006-12-06 Kenichi Handa + + * Version 1.3.4 released. + + * mview.c (VERSION): Changed to 1.3.4. + + * mdump.c (PROGRAM_VERSION): Changed to 1.3.4. + + * mdate.c (VERSION): Changed to 1.3.4. + + * medit.c (VERSION): Changed to 1.3.4. + + * mconv.c (VERSION): Changed to 1.3.4. + +2006-10-27 Kenichi Handa + + * medit.c (surrounding_text_handler): Be sure to set surround text + even if LEN is zero. + +2006-10-16 Kenichi Handa + + * medit.c (create_menu_button): Set XtNinternational to True. + +2006-08-02 Theppitak Karoonboonyanan (tiny change) + + * Makefile.am (common_ldflags, common_ldflags_gui): Use + ${top_builddir}. + +2006-07-19 TAKAHASHI Naoto + + * HELLO.utf8, HELLO.html, HELLO.xml: Add final sukun to Arabic. + +2006-06-23 Kenichi Handa + + * Makefile.am (BUILD_LIBS): Don't increment it conditionally. + + * medit.c (show_cursor): Call mlanguage_name to get English name + of language. + (compare_input_method): Likewise. + (main): Likewise. + +2006-02-22 Kenichi Handa + + * Version 1.3.3 released. + +2006-02-22 Kenichi Handa + + * mview.c: Fix some typo in documention. + + * medit.c: Fix some typo in documention. + + * mdump.c: Fix some typo in documention. + +2006-02-06 Kenichi Handa + + * Version 1.3.2 released. + +2006-02-03 Kenichi Handa + + * mdump.c: Describe the supported color names. + +2006-01-19 Kenichi Handa + + * HELLO.utf8: Fix greek. + + * HELLO.xml: Fix greek. + +2006-01-17 Kenichi Handa + + * mdump.c (main): Use gdImageCreateTrueColor and + gdImageAlphaBlending only if HAVE_GD is 2 or the greater. + +2006-01-16 Kenichi Handa + + * Version 1.3.1 released. + +2006-01-16 Kenichi Handa + + * mdump.c (help_exit): Describe -fg, -bg, -r args. + (main): Handle -fg, -bg args. Use gdImageCreateTrueColor instead + of gdImageCreate. + +2006-01-05 Kenichi Handa + + * HELLO.utf8: Fix Hindi and Oriya. + + * HELLO.xml: Adjusted for the latest HELLO.utf8. + + * HELLO.html: Adjusted for the latest HELLO.utf8. + + * mdate.c (main): Call m17n-view; not mview. + +2005-12-22 Kenichi Handa + + * Version 1.3.0 released. + +2005-12-06 Kenichi Handa + + * medit.c (mt_modified): New variable. + (KeyProc): Update screen if input method modified a text. + (surrounding_text_handler): Set mt_modified to 1 if a text is + deleted. + (main): Fix handling of --font arg. + +2005-12-02 Kenichi Handa + + * medit.c (main): Handle --font arg. + +2005-11-21 Kenichi Handa + + * Makefile.am (bin_PROGRAMS, lib_LTLIBRARIES): Define them + conditionally on WITH_GUI. + +2005-11-11 Kenichi Handa + + * medit.c (surrounding_text_handler): Directly delete characters + instead of calling delete_char. + +2005-11-08 Kenichi Handa + + * medit.c (delete_char): Fix the case of deleting the previous + multiple characters. + (surrounding_text_handler): Check number of characters to delete. + +2005-11-07 Kenichi Handa + + * medit.c (surrounding_text_handler): New function. + (setup_input_methods): Add callback functions for surrounding text + handling. + +2005-10-20 Kenichi Handa + + * medit.c (setup_input_methods): Ignore an input method of name + nil. + +2005-10-14 Kenichi Handa + + * medit.c (main): Don't leave a fontset unfreed. + +2005-10-03 Kenichi Handa + + * mdump.c (main): Make the image tranparent. + +2005-09-27 Kenichi Handa + + * mdump.c (dump_image): If FILTER is "-", print the image to + stdout. + +2005-09-22 Kenichi Handa + + * medit.c (select_input_method): Open an input method if + necessary. Handle left bitmap of input method menus here. + (show_cursor): Don't open an input method here. + (ExposeProc): Likewise. + (FocusInProc): Fix typo (Minput_focus_out -> Minput_focus_in). + (InputMethodProc): Don't handle left bitmap of input method menus + here. + (setup_input_methods): Don't open an input method here. + +2005-09-16 Kenichi Handa + + * medit.c (ButtonProc): Don't reset ic, instead send + Minput_focus_move event to the current input method. + (FocusInProc, FocusOutProc): New functions. + (actions): Add elements for FocusIn and FocusOut. + (main): Add elements for FocusIn and FocusOut to trans2. + +2005-09-12 Kenichi Handa + + * medit.c (redraw): Don't redraw an area where not text is + displayed. + +2005-09-05 Kenichi Handa + + * medit.c: Check HAVE_X11_XAW_COMMAND_H before including X11/*.h. + + * mview.c: Check HAVE_X11_XAW_COMMAND_H before including X11/*.h. + + * Makefile.am (X_LD_FLAGS): Use @X11_LD_FLAGS@ instead of + directory listing libraries. + (PURIFY, purify_medit, purify_mdate): Define them in maintainer + mode. + +2005-08-22 Kenichi Handa + + * mdump.c: Don't include config.h. + + * medit.c: Likewise. + + * mview.c: Likewise. + + * mimx-anthy.c: Likewise. + + * mimx-ispell.c: Likewise. + + * Makefile.am (AM_CPPFLAGS): Set it to @CONFIG_FLAGS@. + +2005-08-18 Kenichi Handa + + * medit.c (main): Adjusted for the change of symbol's language + property (now in lowercase). + + * mdump.c (main): Handle --fontset arg. + +2005-05-19 Kenichi Handa + + * medit.c (main): Explicitly set minput_driver. + +2005-04-28 Kenichi Handa + + * .cvsignore: Change mXXXX to m17n-XXXX. + + * Makefile.am (X_LD_FLAGS): Include @XAW_LD_FLAGS@, not -lXaw. + + * medit.c: Check HAVE_X11_XAW_COMMAND_H, and if it not defined, + add dummy code. + + * mview.c: Check HAVE_X11_XAW_COMMAND_H, and if it not defined, + add dummy code. + +2005-04-15 Kenichi Handa + + * medit.c: Include dlfcn.h. + (Mword): New variable. + (show_cursor): Check Mlanguage text property of the cursor + position only. + (delete_char): Pay attention to the change of line beginning + position because of filling. + (insert_chars): Likewise. + (word_constituent_p, forward_word, backward_word): New functions. + (KeyProc): Assign XK_b and XK_f for back/foreward word. + (line_break): Delete extern. + (LineBreakProc): Use mdraw_default_line_break. + (FilterProc): New function. + (main): Handle --filter arg. Initialize Mword. + + * mdump.c (main): Set control.line_break to + mdraw_default_line_break. + + * Makefile.am (m17n_edit_SOURCES): Don't include linebreak.c. + (m17n_dump_SOURCES): Likewise. + (m17n_edit_LDADD): Don't include @WORDCUT_LD_FLAGS@. + (m17n_dump_LDADD): Likewise. + +2005-03-09 Kenichi Handa + + * HELLO.utf8, HELLO.xml, HELLO.html: Fix Telugu line. + +2005-02-17 Kenichi Handa + + * medit.c (setup_input_methods): Fix for the case that no input + method is available. + +2005-01-12 Kenichi Handa + + * HELLO.utf8, HELLO.xml, HELLO.html: Adjust the encoding of + Myanmar kinzi to the new proposal by Myanmar NLP. + +2004-12-27 Kenichi Handa + + * Version 1.2.0 released. + +2004-12-27 Kenichi Handa + + * M17NEdit.ja: Renamed from MEdit.ja. + + * Makefile.am: Put prefix "m17n-" instead of single "m" to + executables. + (EXTRA_DIST): Include HELLO.html and M17NEdit.ja. + + * mconv.c, mdate.c, mdump.c, medit.c, mview.c: Documentations + changed ("mXXXX" -> "m17n-XXXX"). + +2004-12-21 Kenichi Handa + + * medit.c (ButtonProc): Reset the current input method (if + activated) and insert the produced text. + (KeyProc): Cancel the previous change. + +2004-12-21 Kenichi Handa + + * medit.c (KeyProc): Handle C-\ as resetting input context. + +2004-12-17 Kenichi Handa + + * medit.c (main): Allocagte filename by strdup if not specified. + +2004-12-10 Kenichi Handa + + * mview.c (VERSION): Update to 1.2.0. + + * medit.c (VERSION): Update to 1.2.0. + (main): If filename is not specified, open /dev/null. + + * mdate.c (VERSION): Update to 1.2.0. + + * mconv.c (VERSION): Update to 1.2.0. + +2004-12-09 Kenichi Handa + + * medit.c (SaveProc, DumpImageProc, FileDialogProc, read_file): + Decode by Mcoding_utf_8_full, not Mcoding_utf_8. + +2004-12-09 handa + + * Makefile.am (common_ldflags): Include libm17n-core.la. + (common_ldflags_gui): Include ${common_ldflags} + +2004-12-03 Kenichi Handa + + * mimx-anthy.c (AnthyContext): New member ic. + (new_context): When something goes wrong, return NULL without + creating a context. + (get_context): New function. + (init): Pay attention to the case of multiple calls. + (fini): Likewise. + (convert, change, resize, commit): Use get_context. + + * mimx-ispell.c (face_available): New variable. + (init): Check if GUI APIs are available or not. If not, set + face_available to 0. + (fini): Free a face only if face_available is not zero. + (ispell_word): Put face property only if available. + +2004-10-29 Kenichi Handa + + * medit.c (main): Fix handling of "-s" arg. + +2004-10-12 Kenichi Handa + + * medit.c (KeyProc): Cast buf to `unsigned char *'. + (FaceProc): Call hide_cursor () at first. + +2004-09-27 Kenichi Handa + + * HELLO.html: Add Sinhala. + +2004-09-23 Kenichi Handa + + * HELLO.utf8, HELLO.xml: Add Sinhala. + +2004-09-14 Kenichi Handa + + * medit.c (update_selection): Fix for the case that the selection + is just one line. + +2004-08-27 Kenichi Handa + + * mdump.c (help_exit): Describe about the arg "-r". + (reverse_bit_order, init_reverse_bit_order): Delete them. + (main): Handle the arg "-r". + +2004-08-25 Kenichi Handa + + * medit.c: Adjusted for the member name change + (MDrawGlyphInfo->this -> MDrawGlyphInfo->metics). + + * mdump.c: Adjusted for the member name change + (MDrawGlyphInfo->this -> MDrawGlyphInfo->metics). + +2004-08-16 Kenichi Handa + + * Version 1.1.0 released. + +2004-08-15 Kenichi Handa + + * MEdit.ja: Add Dhivehi. + + * HELLO.utf8, HELLO.xml: Add Oriya and Dhivehi. + + * medit.c (covert_selection): Handle explicit request of + UTF8_STRING. + (ExposeProc): If an initial input method is specifed, activate it. + (setup_input_methods): New arg initial_input_method. If it's not + NULL, set current_input_method to the corresponding index. + (help_exit): Fix help message. + (main): Handle --im and -s command args. + + * mdump.c (help_exit): Fix help message. + +2004-08-09 Kenichi Handa + + * mconv.c (VERSION): Updated to 1.1. + + * mdate.c (VERSION): Likewise. + + * medit.c (VERSION): Likewise. + + * mview.c (VERSION): Likewise. + +2004-07-28 Kenichi Handa + + * HELLO.utf8: Add language names for Telugu and Gujarati. + + * HELLO.xml: Add language names for Telugu and Gujarati. + +2004-07-26 Kenichi Handa + + * medit.c (redraw_cursor): Fix checking of redrawing area. + (set_input_method_spot): Don't check face if the buffer is empty. + (show_cursor): Likewise. + (delete_char): Fix adjustment of nchars. + (CursorProc): Call update_cursor. + +2004-07-23 Kenichi Handa + + * HELLO.xml: Add Myanmar. + + * HELLO.utf8: Add Myanmar. + +2004-07-22 Kenichi Handa + + * medit.c (get_selection): If decoding fails and *type is not + XA_UTF8_STRING, try to get selection value of type XA_UTF8_STRING. + +2004-07-20 Kenichi Handa + + * medit.c (main): If frame creation is falied, exit by error. + Call M17N_FINI after destroying the application context. + +2004-07-18 Kenichi Handa + + * Makefile.am (common_ldflags): Don't include + ${top_srcdir}/src/libm17n-core.la. + +2004-07-07 Kenichi Handa + + * medit.c (Mcoding_compound_text): New variable. + (covert_selection): Fix previous change. + (main): Set Mcoding_compound_text. + +2004-07-06 Kenichi Handa + + * mdump.c: Cancel previous change. + + * Makefile.am (X_LD_FLAGS): Fix the order of linking. + (medit_LDADD, mview_LDADD, mdump_LDADD): Cancel previous change. + + * HELLO.xml: Add Punjabi, Kannada, Telugu, and Gujarati. + + * medit.c (covert_selection): If X_HAVE_UTF8_STRING is defined and + target is XA_UTF8_STRING, encode by utf-8. + (get_selection): If X_HAVE_UTF8_STRING is defined and *type is + XA_UTF8_STRING, decode by utf-8. + +2004-07-05 Kenichi Handa + + * HELLO.utf8: Add Kannada. + +2004-06-30 Kenichi Handa + + * mdump.c: Include instead of . + + * Makefile.am (X_LD_FLAGS): New variable. + (medit_LDADD, mview_LDADD, mdump_LDADD): Add all depending + libraries. + (medit_LDFLAGS, mview_LDFLAGS, mdump_LDFLAGS): Delete them. + (libmimx_anthy_la_LIBADD): Add @ANTHY_LD_FLAGS@. + (libmimx_anthy_la_LDFLAGS): Delete @ANTHY_LD_FLAGS@. + +2004-06-25 TAKAHASHI Naoto + + * HELLO.utf8: Add Punjabi. + +2004-06-24 Kenichi Handa + + * Makefile.am: (libmimx_ispell_la_LDFLAGS) + (libmimx_anthy_la_LDFLAGS): Add -module. + +2004-06-23 Kenichi Handa + + * Makefile.am (medit_LDFLAGS, mview_LDFLAGS): Cancel the previous + change. + + * medit.c (redraw_cursor): Refer to cursor.logical_width instead + of cursor.this.width. + +2004-06-21 Kenichi Handa + + * Makefile.am (medit_LDFLAGS, mview_LDFLAGS): Include -lX11 and + -lXt. + +2004-06-17 Kenichi Handa + + * mdump.c (main): Don't set control.as_image to 1. + +2004-06-16 Kenichi Handa + + * mdump.c (main): Fix typo of error message. + + * medit.c (face_freeserif): New variable. + (face_table): Add an entry for freeserif. + (main): Initialized and free face_freeserif. + +2004-06-15 Kenichi Handa + + * mdump.c: Add command line arguments --family and --language. + (help_exit): Print info about those arguemnts. + (main): Make family name to lowercase. + +2004-06-04 Kenichi Handa + + * mconv.c (compare_coding_name): New function. + (list_coding): Sort the list of codings by their names. + +2004-06-03 Kenichi Handa + + * medit.c (InputMethodInfo): New type. + (input_method_table): Type changed to `InputMethodInfo *'. + (select_input_method): Adjusted for the change of + input_method_table. + (show_cursor): Open an input method here if necessary. + (compare_input_method): Adjusted for the change of + input_method_table. + (setup_input_methods): Likewise. Don't open input methods here + except for XIM. + (main): Adjusted for the change of input_method_table. + + * mconv.c (main): Close `in' and `out'. + + * HELLO.utf8: Fix Greek line. + + * HELLO.xml: Fix Greek line. + +2004-05-28 Kenichi Handa + + * Makefile.am (VINFO): New variable. + (libmimx_ispell_la_LDFLAGS, libmimx_anthy_la_LDFLAGS): Include + ${VINFO}. + + * mdump.c (PROGRAM_VERSION): Renamed from VERSION. + (main): Use PROGRAM_VERSION. + + * medit.c (main): Make face_input_status copy of face_default. + +2004-05-27 Kenichi Handa + + * medit.c (show_cursor): Check hline->width and box->width. + (main): Set reverse videomode in a face for selection. + + * mdump.c: Include config.h. Include instead of + . If not HAVE_FREETYPE nor HAVE_GD, define a pseudo + function main that just print an error message. + (help_exit): Adjusted for the change of spec. + (dump_image): Argument changed. Dump PNG image instead of PBM. + (main): Adjusted for the change of spec. + + * Makefile.am (common_ldflags_gui): Renamed from + common_ldflags_X. Set to .../libm17n-gui.la. Referrer changed. + (mdump_LDFLAGS): Include @GD_LD_FLAGS@ + + * HELLO.xml: Add Bengali. + +2004-05-21 Kenichi Handa + + * HELLO.utf8: Add Bengali. + +2004-05-20 Kenichi Handa + + * medit.c (redraw): If contro.anti_alias is nonzero, always clear. + (ButtonMoveProc): Don't give control.anti_alias to redraw. + (default_face_list): New variable. + (FaceProc): If no selection, change the default face. + (main): Initialize and finalize default_face_list. + +2004-04-27 Kenichi Handa + + * mimx-ispell.c: Add coding tag euc-jp. + + * mimx-anthy.c: Add coding tag euc-jp. + + * medit.c: Add coding tag euc-jp. + (ButtonMoveProc): Full redraw if we are using anti-aliased text. + (main): Set control.anti_alias to 1. + + * mdump.c: Add coding tag euc-jp. + + * mdate.c: Add coding tag euc-jp. + + * mconv.c: Add coding tag euc-jp. + +2004-04-20 Kenichi Handa + + * Makefile.am (medit_LDFLAGS): Include X_PRE_LIBS, XLIBS, + X_EXTRA_LIBS. + (mview_LDFLAGS): Likewise. + + * linebreak.c: Don't include wordcut/xmalloc.h, wordcut/path.h. + +2004-03-29 Kenichi Handa + + * Version 1.0 Patch Level 2 released. + +2004-03-19 Kenichi Handa + + * Version 1.0 Patch Level 1 released. + +2004-03-19 Kenichi Handa + + * medit.c (VERSION): Changed to 1.0.1. + (update_selection): Fix for the case that the selected region is + expanded to the opposite direction. + (ButtonMoveProc): Likewise. + (main): Use alloca instead of malloc for allocating menu names. + Free several memory areas and GCs. + +2004-03-12 Kenichi Handa + + * medit.c (input_status_control): New variable. + (input_status): Use input_status_control. + (main): Initialize input_status_control. + +2004-03-01 Kenichi Handa + + * Version 1.0 released. + + +Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + 2013, 2014 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + +This file is part of the m17n library. + +The m17n 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 m17n 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 m17n library; if not, write to the Free +Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. diff --git a/example/HELLO-ja.utf8 b/example/HELLO-ja.utf8 new file mode 100644 index 0000000..102fcbc --- /dev/null +++ b/example/HELLO-ja.utf8 @@ -0,0 +1,30 @@ +ヨーロッパ + 英語 (English) Hello + フランス語 (français) Bonjour, Salut + ドイツ語 (Deutsch) Guten Tag, Grüß Gott + スロバキア語 (slovensky) Dobrý deň + ロシア語 (русский) Здравствуйте! + ギリシャ語 (ελληνικά) Γειάσας + +中近東・アフリカ + トルコ語 (Türkçe) Merhaba + グルジア語 (ქართული) გამარჯობათ! + アラビア語 (اَلْعَرَبِيَّةُ)‎ اَلسَّلَامُ عَلَيْكُم + ペルシャ語 (فارسی)‎ سلام عليکم + ヘブライ語 (עִבְרִית)‎ שָׁלוֹם + アムハラ語 (አማርኛ) ሠላም + +南・東南アジア + ヒンディー語 (हिंदी) नमस्ते, नमस्कार । + マラヤラム語(മലയാളം) നമസ്കാരം + タミール語 (தமிழ்) வணக்கம் + チベット語 (བོད་སྐད་) བཀྲ་ཤིས་བདེ་ལེགས༎ (ex: བསྒྲུབས, ཧཱུཾ) + クメール語 (ខ្មៃរ) ជំរាបសួរ (ex: ក្ក្រឿ៌) + ベトナム語 (Tiếng Việt) Chào bạn + タイ語 (ภาษาไทย) สวัสดีครับ, สวัสดีค่ะ + ラオ語 (ພາສາລາວ) ສະບາຍດີ, ຂໍໃຫ້ໂຊກດີ + +東アジア + 日本語 こんにちは + 中国語 (汉语,普通话) 你好 + 韓国語 (한글) 안녕하세요 diff --git a/example/HELLO-ja.xml b/example/HELLO-ja.xml new file mode 100644 index 0000000..9a1eeaf --- /dev/null +++ b/example/HELLO-ja.xml @@ -0,0 +1,66 @@ + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + +ヨーロッパ + 英語 (English) Hello + フランス語 (français) Bonjour, Salut + ドイツ語 (Deutsch) Guten Tag, Grüß Gott + スロバキア語 (slovensky) Dobrý deň + ロシア語 (русский) Здравствуйте! + ギリシャ語 (ελληνικά) Γειάσας + +中近東・アフリカ + トルコ語 (Türkçe) Merhaba + グルジア語 (ქართული) გამარჯობათ! + アラビア語 (اَلْعَرَبِيَّةُ)‎ اَلسَّلَامُ عَلَيْكُم + ペルシャ語 (فارسی)‎ سلام عليکم + ヘブライ語 (עִבְרִית)‎ שָׁלוֹם + アムハラ語 (አማርኛ) ሠላም + +南・東南アジア + ヒンディー語 (हिंदी) नमस्ते, नमस्कार । + マラヤラム語(മലയാളം) നമസ്കാരം + タミール語 (தமிழ்) வணக்கம் + チベット語 (བོད་སྐད་) བཀྲ་ཤིས་བདེ་ལེགས༎ (ex: བསྒྲུབས, ཧཱུཾ) + クメール語 (ខ្មៃរ) ជំរាបសួរ (ex: ក្ក្រឿ៌) + ベトナム語 (Tiếng Việt) Chào bạn + タイ語 (ภาษาไทย) สวัสดีครับ, สวัสดีค่ะ + ラオ語 (ພາສາລາວ) ສະບາຍດີ, ຂໍໃຫ້ໂຊກດີ + +東アジア + 日本語 こんにちは + 中国語 (汉语,普通话) 你好 + 韓国語 (한글) 안녕하세요 + diff --git a/example/HELLO.html b/example/HELLO.html new file mode 100644 index 0000000..d5921f3 --- /dev/null +++ b/example/HELLO.html @@ -0,0 +1,190 @@ + + + + + + Hello World! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Europe
Englishhello
FrenchfrançaisBonjour, Salut
GermanDeutschGuten Tag, Grüß Gott
SlovakslovenskyDobrý deň
RussianрусскийЗдравствуйте!
GreekελληνικάΓειά σας
ArmenianհայերենԲարեւ։
Georgianქართულიგამარჯობათ!
Middle Near East/Africa
TurkishTürkçeMerhaba
Hebrewעִבְרִיתשָׁלוֹם
Arabicاَلْعَرَبِيَّةُاَلسَّلَامُ عَلَيْكُمْ
Persianفارسیسلام عليکم
Dhivehiދިވެހިބަސްއައްސަލާމު އަލައިކުމް
Amharicአማርኛሠላም
South Asia
Hindiहिन्दीनमस्ते, नमस्कार ।
Bengaliবাংলানমস্কার
Punjabiਪੰਜਾਬੀਸਤਿ ਸ਼੍ਰੀ ਅਕਾਲ
Gujaratiગુજરાતીનમસ્તે
Oriyaଓଡ଼ିଆଶୁଣିବେ
Tamilதமிழ்வணக்கம்
Teluguతెలుగునమస్కారం
Kannadaಕನ್ನಡನಮಸ್ಕಾರ
Malayalamമലയാളംനമസ്കാരം
Sinhalaසිංහලආයුබෝවන්
Tibetanབོད་སྐད་བཀྲ་ཤིས་བདེ་ལེགས༎
South-East Asia
Thaiภาษาไทยสวัสดีครับ, สวัสดีค่ะ
Laoພາສາລາວສະບາຍດີ, ຂໍໃຫ້ໂຊກດີ
Myanmarမ္ရန္‌မာမင္‍ဂလာပာ
Khmerខ្មៃរជំរាបសួរ
VietnameseTiếng ViệtChào bạn
East Asia
Japanese日本語こんにちは
Chinese汉语,普通话你好
Korean한글안녕하세요
+ + diff --git a/example/HELLO.utf8 b/example/HELLO.utf8 new file mode 100644 index 0000000..9934932 --- /dev/null +++ b/example/HELLO.utf8 @@ -0,0 +1,41 @@ +Europe + English Hello + French (français) Bonjour, Salut + German (Deutsch) Guten Tag, Grüß Gott + Slovak (slovensky) Dobrý deň + Russian (русский) Здравствуйте! + Greek (ελληνικά) Γειά σας + Armenian (հայերեն) Բարեւ։ + Georgian (ქართული) გამარჯობათ! + +Middle Near East/Africa + Turkish (Türkçe) Merhaba + Hebrew (עִבְרִית)‎ שָׁלוֹם + Arabic (اَلْعَرَبِيَّةُ)‎ اَلسَّلَامُ عَلَيْكُمْ + Persian (فارسی)‎ سلام عليکم + Dhivehi (ދިވެހިބަސް)‎ އައްސަލާމު އަލައިކުމް + Amharic (አማርኛ) ሠላም + +South/South-East Asia + Hindi (हिंदी) नमस्ते, नमस्कार । + Bengali (বাংলা) নমস্কার + Punjabi (ਪੰਜਾਬੀ) ਸਤਿ ਸ਼੍ਰੀ ਅਕਾਲ + Gujarati (ગુજરાતી) નમસ્તે + Oriya (ଓଡ଼ିଆ) ଶୁଣିବେ + Tamil (தமிழ்) வணக்கம் + Telugu (తెలుగు) నమస్కారం + Kannada (ಕನ್ನಡ) ನಮಸ್ಕಾರ + Malayalam (മലയാളം) നമസ്കാരം (ex: ന+്+ര=ന്ര) + Sinhala (සිංහල) ආයුබෝවන් + Tibetan (བོད་སྐད་) བཀྲ་ཤིས་བདེ་ལེགས༎ (ex: བསྒྲུབས, ཧཱུཾ) + Thai (ภาษาไทย) สวัสดีครับ, สวัสดีค่ะ + Lao (ພາສາລາວ) ສະບາຍດີ, ຂໍໃຫ້ໂຊກດີ + Myanmar (မ္ရန္‌မာ) မင္‍ဂလာပာ (before Unicode 5.1) + Myanmar (မြန်မာ) မင်္ဂလာပါ (after Unicode 5.1) + Khmer (ភាសាខ្មែរ) ជំរាបសួរ (ex: ក៊្ក្រឿ) + Vietnamese (Tiếng Việt) Chào bạn + +East Asia + Chinese (汉语,普通话) 你好 + Japanese (日本語) こんにちは + Korean (한글) 안녕하세요 diff --git a/example/HELLO.xml b/example/HELLO.xml new file mode 100644 index 0000000..3a9d852 --- /dev/null +++ b/example/HELLO.xml @@ -0,0 +1,88 @@ + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Europe + English Hello + French (français) Bonjour, Salut + German (Deutsch) Guten Tag, Grüß Gott + Slovak (slovensky) Dobrý deň + Russian (русский) Здравствуйте! + Greek (ἑλληνικά) Γειά σας + Armenian (հայերեն) Բարեւ։ + Georgian (ქართული) გამარჯობათ! + +Middle Near East/Africa + Turkish (Türkçe) Merhaba + Hebrew (עִבְרִית)‎ שָׁלוֹם + Arabic (اَلْعَرَبِيَّةُ)‎ اَلسَّلَامُ عَلَيْكُمْ + Persian (فارسی)‎ سلام عليکم + Dhivehi (ދިވެހިބަސް)‎ އައްސަލާމު އަލައިކުމް + Amharic (አማርኛ) ሠላም + +South/South-East Asia + Hindi (हिन्दी) नमस्ते, नमस्कार । + Bengali (বাংলা) নমস্কার + Punjabi (ਪੰਜਾਬੀ) ਸਤਿ ਸ਼੍ਰੀ ਅਕਾਲ + Gujarati (ગુજરાતી) નમસ્તે + Oriya (ଓଡ଼ିଆ) ଶୁଣିବେ + Tamil (தமிழ்) வணக்கம் + Telugu (తెలుగు) నమస్కారం + Kannada (ಕನ್ನಡ) ನಮಸ್ಕಾರ + Malayalam (മലയാളം) നമസ്കാരം (ex: ന+്+ര=ന്ര) + Sinhala (සිංහල) ආයුබෝවන් + Tibetan (བོད་སྐད་) བཀྲ་ཤིས་བདེ་ལེགས༎ (ex: བསྒྲུབས, ཧཱུཾ) + Thai (ภาษาไทย) สวัสดีครับ, สวัสดีค่ะ + Lao (ພາສາລາວ) ສະບາຍດີ, ຂໍໃຫ້ໂຊກດີ + Myanmar (မ္ရန္‌မာ) မင္‍ဂလာပာ + Khmer (ខ្មៃរ) ជំរាបសួរ (ex: ក្ក្រឿ៌) + Vietnamese (Tiếng Việt) Chào bạn + +East Asia + Chinese (汉语,普通话) 你好 + Japanese (日本語) こんにちは + Korean (한글) 안녕하세요 + diff --git a/example/M17NEdit.ja b/example/M17NEdit.ja new file mode 100644 index 0000000..fbc08b9 --- /dev/null +++ b/example/M17NEdit.ja @@ -0,0 +1,154 @@ +! -*- coding: euc-jp; -*- +*.fontSet: -etl-fixed-medium-r-normal--24-*-*-*-*,-*-*-medium-r-normal--24-*-*-*-* +*.international: True +*.File.label: �ե����� +*.Cursor.label: �������� +*.Bidi.label: ������� +*.LineBreak.label: ��ʬ�� +*.InputMethod.label: ���ϥ᥽�å� +*.Face.label: �ե����� +*.Lang.label: ���� +*.Size.label: ������ +*.Family.label: �ե��ߥ꡼ +*.Style.label: �������� +*.Color.label: �� +*.Misc.label: ����¾ +*.Pop Face.label: �ݥå� +*Abkhazian.label:���֥ϥ��� +*Afar.label:���ե���� +*Afrikaans.label:���եꥫ���󥹸� +*Albanian.label:����Х˥��� +*Amharic.label:����ϥ�� +*Arabic.label:����ӥ��� +*Armenian.label:�����˥��� +*Assamese.label:���å���� +*Aymara.label:�����ޥ�� +*Azerbaijani.label:������Х������� +*Bashkir.label:�Х��奭����� +*Basque.label:�Х����� +*Bengali.label:�٥󥬥�� +*Bhutani.label:�֡������ +*Bihari.label:�ӥϡ���� +*Bislama.label:�ӥ���޸� +*Breton.label:�֥�ȥ�� +*Bulgarian.label:�֥륬�ꥢ�� +*Burmese.label:�ӥ�޸� +*Byelorussian.label:��������� +*Cambodian.label:����ܥ����� +*Catalan.label:�������˥��� +*Chinese.label:���� +*Corsican.label:���륷���� +*Croatian.label:������������ +*Czech.label:�������� +*Dhivehi.label:�ǥ��٥Ҹ� +*Danish.label:�ǥ�ޡ����� +*Dutch.label:�������� +*English.label:�Ѹ� +*Esperanto.label:�����ڥ��� +*Estonian.label:�����ȥ˥��� +*Faeroese.label:�ե��������� +*Farsi.label:�ڥ륷���� +*Fiji.label:�ե������� +*Finnish.label:�ե�����ɸ� +*French.label:�ե�󥹸� +*Frisian.label:�եꥸ���� +*Galician.label:���ꥷ���� +*Gaelic(Scottish).label:�������ʥ����åȥ��ɡ� +*Gaelic(Manx).label:�������ʥޥ���� +*Georgian.label:���른���� +*German.label:�ɥ��ĸ� +*Greek.label:���ꥷ���� +*Greenlandic.label:���꡼����ɸ� +*Guarani.label:���ˡ��� +*Gujarati.label:������顼�ȸ� +*Hausa.label:�ϥ����� +*Hebrew.label:�إ֥饤�� +*Hindi.label:�ҥ�ǥ����� +*Hungarian.label:�ϥ󥬥꡼�� +*Icelandic.label:���������ɸ� +*Indonesian.label:����ɥͥ����� +*Inuktitut.label:���̥��ƥ��ȥåȸ� +*Inupiak.label:���̥ԥ��å��� +*Irish.label:��������ɸ� +*Italian.label:�����ꥢ�� +*Japanese.label:���ܸ� +*Javanese.label:������ +*Kannada.label:����ʥ��� +*Kashmiri.label:������ߡ���� +*Kazakh.label:�����ո� +*Kinyarwanda.label:������� +*Kirghiz.label:���륮���� +*Kirundi.label:���ǥ��� +*Korean.label:ī���� +*Kurdish.label:����ɸ� +*Laothian.label:�饪�� +*Latin.label:��ƥ�� +*Latvian.label:��ȥ������� +*Lingala.label:��󥬥�� +*Lithuanian.label:��ȥ��˥��� +*Macedonian.label:�ޥ��ɥ˥��� +*Malagasy.label:�ޥ饬���� +*Malay.label:����� +*Malayalam.label:�ޥ�䡼���� +*Maltese.label:�ޥ륿�� +*Maori.label:�ޥ���� +*Marathi.label:�ޥ顼�ƥ����� +*Moldavian.label:�����ӥ��� +*Mongolian.label:��󥴥�� +*Nauru.label:�ʥ���� +*Nepali.label:�ͥѡ���� +*Norwegian.label:�Υ륦������ +*Occitan.label:�ץ������󥹸� +*Oriya.label:����䡼�� +*Oromo.label:���å�� +*Pashto.label:�ѥ���ȡ��� +*Polish.label:�ݡ����ɸ� +*Portuguese.label:�ݥ�ȥ���� +*Punjabi.label:�ѥ󥸥㡼�ָ� +*Quechua.label:�����奢�� +*Rhaeto-Romance.label:��ȡ����ޥ󥹸� +*Romanian.label:�롼�ޥ˥��� +*Russian.label:�������� +*Samoan.label:���⥢�� +*Sangro.label:���󥴸� +*Sanskrit.label:���󥹥���å� +*Serbian.label:����ӥ��� +*Serbo-Croatian.label:����ӥ��������������� +*Sesotho.label:���ȸ� +*Setswana.label:�ĥ�ʸ� +*Shona.label:����ʸ� +*Sindhi.label:����ɸ� +*Sinhala.label:����ϥ�� +*Siswati.label:����ƥ��� +*Slovak.label:�����Х����� +*Slovenian.label:�����٥˥��� +*Somali.label:���ޥ�� +*Spanish.label:���ڥ���� +*Sundanese.label:������� +*Swahili.label:����ҥ�� +*Swedish.label:���������ǥ�� +*Tagalog.label:���������� +*Tajik.label:�������� +*Tamil.label:���ߡ���� +*Tatar.label:��������� +*Telugu.label:�ƥ륰�� +*Thai.label:������ +*Tibetan.label:���٥åȸ� +*Tigrinya.label:�ƥ�����˥��� +*Tonga.label:�ȥ󥬸� +*Tsonga.label:�ĥ��󥬸� +*Turkish.label:�ȥ륳�� +*Turkmen.label:�ȥ륯���� +*Twi.label:���奤�� +*Uighur.label:��������� +*Ukrainian.label:�����饤�ʸ� +*Urdu.label:����ɥ����� +*Uzbek.label:�����٥��� +*Vietnamese.label:�٥ȥʥ�� +*Volapuk.label:������ԥ奯 +*Welsh.label:�������륺�� +*Wolof.label:�������ո� +*Xhosa.label:������ +*Yiddish.label:���ǥ��å���� +*Yoruba.label:���и� +*Zulu.label:�����롼�� diff --git a/example/Makefile.am b/example/Makefile.am new file mode 100644 index 0000000..4e7b24e --- /dev/null +++ b/example/Makefile.am @@ -0,0 +1,95 @@ +# Makefile.am -- example level Makefile for the m17n library. +# Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010, 2011, 2012 +# National Institute of Advanced Industrial Science and Technology (AIST) +# Registration Number H15PRO112 + +# This file is part of the m17n library. + +# The m17n 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 m17n 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 m17n library; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +## Process this file with Automake to create Makefile.in + +## Note: Source files have preifx "m" but executables have prefix +## "m17n-" to avoid confliction of program names. + +BASICPROGS = m17n-conv +if WITH_GUI +bin_PROGRAMS = $(BASICPROGS) m17n-view m17n-date m17n-dump m17n-edit +else +bin_PROGRAMS = $(BASICPROGS) +endif + +common_ldflags = ${top_builddir}/src/libm17n-core.la ${top_builddir}/src/libm17n.la +common_ldflags_gui = ${common_ldflags} ${top_builddir}/src/libm17n-flt.la ${top_builddir}/src/libm17n-gui.la +AM_CPPFLAGS=-I$(top_srcdir)/src @CONFIG_FLAGS@ + +m17n_date_SOURCES = mdate.c +m17n_date_LDADD = ${common_ldflags} + +m17n_conv_SOURCES = mconv.c +m17n_conv_LDADD = ${common_ldflags} + +X_LD_FLAGS = ${X_PRE_LIBS} ${X_LIBS} @XAW_LD_FLAGS@ @X11_LD_FLAGS@ ${X_EXTRA_LIBS} + +m17n_edit_SOURCES = medit.c +m17n_edit_LDADD = ${X_LD_FLAGS} ${common_ldflags_gui} -ldl + +m17n_view_SOURCES = mview.c +m17n_view_LDADD = ${X_LD_FLAGS} ${common_ldflags_gui} + +m17n_dump_SOURCES = mdump.c +m17n_dump_LDADD = @GD_LD_FLAGS@ ${common_ldflags_gui} + +# Input method data files. + +pkgdatadir=$(datadir)/m17n + +EXTRA_DIST = \ + .gdbinit .gdb.util \ + HELLO.utf8 HELLO.xml HELLO-ja.utf8 HELLO-ja.xml HELLO.html M17NEdit.ja + +# External modules used by the above input methods. + +moduledir = ${libdir}/@M17N_MODULE_DIR@ + +BASICBUILDS = libmimx-anthy.la +if WITH_GUI +BUILD_LIBS = $(BASICBUILDS) libmimx-ispell.la +else +BUILD_LIBS = $(BASICBUILDS) +endif +module_LTLIBRARIES = $(BUILD_LIBS) + +libmimx_ispell_la_SOURCES = mimx-ispell.c +libmimx_ispell_la_LIBADD = ${common_ldflags_gui} +libmimx_ispell_la_LDFLAGS = -avoid-version -module +libmimx_anthy_la_SOURCES = mimx-anthy.c +libmimx_anthy_la_LIBADD = ${common_ldflags} @ANTHY_LD_FLAGS@ +libmimx_anthy_la_LDFLAGS = -avoid-version -module + +if MAINTAINER_MODE + +# Special targets to test the m17n library with Purify. + +PURIFY=/usr/local/rational/releases/purify.sol.2002.05.00/purify + +purify_medit: medit ../src/.libs/libm17n-core.so ../src/.libs/libm17n.so ../src/.libs/libm17n-X.so linebreak.c + ${PURIFY} gcc -g medit.o linebreak.o -lXaw -lXmu -L/usr/X11R6/lib -R/usr/X11R6/lib -lSM -lICE -lX11 -lXt -L../src/.libs -lm17n-core -lm17n -lm17n-X -ldl + +purify_mdate: mdate.o ../src/.libs/libm17n.so ../src/.libs/libm17n-X.so + ${PURIFY} gcc -g mdate.o -lXaw -lXmu -L/usr/X11R6/lib -R/usr/X11R6/lib -lSM -lICE -lX11 -lXt -L../src/.libs -lm17n -lm17n-X -ldl + +endif diff --git a/example/Makefile.in b/example/Makefile.in new file mode 100644 index 0000000..9f00f00 --- /dev/null +++ b/example/Makefile.in @@ -0,0 +1,932 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am -- example level Makefile for the m17n library. +# Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010, 2011, 2012 +# National Institute of Advanced Industrial Science and Technology (AIST) +# Registration Number H15PRO112 + +# This file is part of the m17n library. + +# The m17n 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 m17n 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 m17n library; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@WITH_GUI_FALSE@bin_PROGRAMS = $(am__EXEEXT_1) +@WITH_GUI_TRUE@bin_PROGRAMS = $(am__EXEEXT_1) m17n-view$(EXEEXT) \ +@WITH_GUI_TRUE@ m17n-date$(EXEEXT) m17n-dump$(EXEEXT) \ +@WITH_GUI_TRUE@ m17n-edit$(EXEEXT) +subdir = example +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \ + $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \ + $(top_srcdir)/m4/inttypes-pri.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \ + $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \ + $(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(moduledir)" "$(DESTDIR)$(bindir)" +LTLIBRARIES = $(module_LTLIBRARIES) +libmimx_anthy_la_DEPENDENCIES = $(common_ldflags) +am_libmimx_anthy_la_OBJECTS = mimx-anthy.lo +libmimx_anthy_la_OBJECTS = $(am_libmimx_anthy_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libmimx_anthy_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libmimx_anthy_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +@WITH_GUI_FALSE@am_libmimx_anthy_la_rpath = -rpath $(moduledir) +@WITH_GUI_TRUE@am_libmimx_anthy_la_rpath = -rpath $(moduledir) +am__DEPENDENCIES_1 = $(common_ldflags) \ + ${top_builddir}/src/libm17n-flt.la \ + ${top_builddir}/src/libm17n-gui.la +libmimx_ispell_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libmimx_ispell_la_OBJECTS = mimx-ispell.lo +libmimx_ispell_la_OBJECTS = $(am_libmimx_ispell_la_OBJECTS) +libmimx_ispell_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libmimx_ispell_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +@WITH_GUI_TRUE@am_libmimx_ispell_la_rpath = -rpath $(moduledir) +am__EXEEXT_1 = m17n-conv$(EXEEXT) +PROGRAMS = $(bin_PROGRAMS) +am_m17n_conv_OBJECTS = mconv.$(OBJEXT) +m17n_conv_OBJECTS = $(am_m17n_conv_OBJECTS) +m17n_conv_DEPENDENCIES = $(common_ldflags) +am_m17n_date_OBJECTS = mdate.$(OBJEXT) +m17n_date_OBJECTS = $(am_m17n_date_OBJECTS) +m17n_date_DEPENDENCIES = $(common_ldflags) +am_m17n_dump_OBJECTS = mdump.$(OBJEXT) +m17n_dump_OBJECTS = $(am_m17n_dump_OBJECTS) +m17n_dump_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_m17n_edit_OBJECTS = medit.$(OBJEXT) +m17n_edit_OBJECTS = $(am_m17n_edit_OBJECTS) +am__DEPENDENCIES_2 = +am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_2) \ + $(am__DEPENDENCIES_2) +m17n_edit_DEPENDENCIES = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_1) +am_m17n_view_OBJECTS = mview.$(OBJEXT) +m17n_view_OBJECTS = $(am_m17n_view_OBJECTS) +m17n_view_DEPENDENCIES = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libmimx_anthy_la_SOURCES) $(libmimx_ispell_la_SOURCES) \ + $(m17n_conv_SOURCES) $(m17n_date_SOURCES) $(m17n_dump_SOURCES) \ + $(m17n_edit_SOURCES) $(m17n_view_SOURCES) +DIST_SOURCES = $(libmimx_anthy_la_SOURCES) \ + $(libmimx_ispell_la_SOURCES) $(m17n_conv_SOURCES) \ + $(m17n_date_SOURCES) $(m17n_dump_SOURCES) $(m17n_edit_SOURCES) \ + $(m17n_view_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ + ChangeLog +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +# Input method data files. +pkgdatadir = $(datadir)/m17n +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +ANTHY_CFLAGS = @ANTHY_CFLAGS@ +ANTHY_LD_FLAGS = @ANTHY_LD_FLAGS@ +ANTHY_LIBS = @ANTHY_LIBS@ +API_VERSION = @API_VERSION@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_VISIBILITY = @CFLAG_VISIBILITY@ +CONFIG_FLAGS = @CONFIG_FLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FONTCONFIG_LD_FLAGS = @FONTCONFIG_LD_FLAGS@ +FREETYPE_LD_FLAGS = @FREETYPE_LD_FLAGS@ +FRIBIDI_LD_FLAGS = @FRIBIDI_LD_FLAGS@ +GD_LD_FLAGS = @GD_LD_FLAGS@ +GENCAT = @GENCAT@ +GETTEXTDIR = @GETTEXTDIR@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GLIBC2 = @GLIBC2@ +GLIBC21 = @GLIBC21@ +GLIB_2_0_CFLAGS = @GLIB_2_0_CFLAGS@ +GLIB_2_0_LIBS = @GLIB_2_0_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +HAVE_ASPRINTF = @HAVE_ASPRINTF@ +HAVE_FREETYPE_CONFIG = @HAVE_FREETYPE_CONFIG@ +HAVE_FRIBIDI_CONFIG = @HAVE_FRIBIDI_CONFIG@ +HAVE_ISPELL = @HAVE_ISPELL@ +HAVE_M17N_DB = @HAVE_M17N_DB@ +HAVE_OTFLIB_CONFIG = @HAVE_OTFLIB_CONFIG@ +HAVE_PKG_CONFIG = @HAVE_PKG_CONFIG@ +HAVE_POSIX_PRINTF = @HAVE_POSIX_PRINTF@ +HAVE_SNPRINTF = @HAVE_SNPRINTF@ +HAVE_VISIBILITY = @HAVE_VISIBILITY@ +HAVE_WPRINTF = @HAVE_WPRINTF@ +HAVE_XFT_CONFIG = @HAVE_XFT_CONFIG@ +HAVE_XML2_CONFIG = @HAVE_XML2_CONFIG@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLBISON = @INTLBISON@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBPTH = @LIBPTH@ +LIBPTH_PREFIX = @LIBPTH_PREFIX@ +LIBS = @LIBS@ +LIBTHAI_CFLAGS = @LIBTHAI_CFLAGS@ +LIBTHAI_LIBS = @LIBTHAI_LIBS@ +LIBTHREAD = @LIBTHREAD@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBC = @LTLIBC@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBPTH = @LTLIBPTH@ +LTLIBTHREAD = @LTLIBTHREAD@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +M17NDIR = @M17NDIR@ +M17N_MODULE_DIR = @M17N_MODULE_DIR@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTF_LD_FLAGS = @OTF_LD_FLAGS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSUB = @POSUB@ +POW_LIB = @POW_LIB@ +PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +THAI_WORDSEG_LD_FLAGS = @THAI_WORDSEG_LD_FLAGS@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WINDRES = @WINDRES@ +WOE32 = @WOE32@ +WOE32DLL = @WOE32DLL@ +WORDCUT_CFLAGS = @WORDCUT_CFLAGS@ +WORDCUT_LIBS = @WORDCUT_LIBS@ +X11_LD_FLAGS = @X11_LD_FLAGS@ +XAW_LD_FLAGS = @XAW_LD_FLAGS@ +XFT2_LD_FLAGS = @XFT2_LD_FLAGS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +XMKMF = @XMKMF@ +XML2_LD_FLAGS = @XML2_LD_FLAGS@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +BASICPROGS = m17n-conv +common_ldflags = ${top_builddir}/src/libm17n-core.la ${top_builddir}/src/libm17n.la +common_ldflags_gui = ${common_ldflags} ${top_builddir}/src/libm17n-flt.la ${top_builddir}/src/libm17n-gui.la +AM_CPPFLAGS = -I$(top_srcdir)/src @CONFIG_FLAGS@ +m17n_date_SOURCES = mdate.c +m17n_date_LDADD = ${common_ldflags} +m17n_conv_SOURCES = mconv.c +m17n_conv_LDADD = ${common_ldflags} +X_LD_FLAGS = ${X_PRE_LIBS} ${X_LIBS} @XAW_LD_FLAGS@ @X11_LD_FLAGS@ ${X_EXTRA_LIBS} +m17n_edit_SOURCES = medit.c +m17n_edit_LDADD = ${X_LD_FLAGS} ${common_ldflags_gui} -ldl +m17n_view_SOURCES = mview.c +m17n_view_LDADD = ${X_LD_FLAGS} ${common_ldflags_gui} +m17n_dump_SOURCES = mdump.c +m17n_dump_LDADD = @GD_LD_FLAGS@ ${common_ldflags_gui} +EXTRA_DIST = \ + .gdbinit .gdb.util \ + HELLO.utf8 HELLO.xml HELLO-ja.utf8 HELLO-ja.xml HELLO.html M17NEdit.ja + + +# External modules used by the above input methods. +moduledir = ${libdir}/@M17N_MODULE_DIR@ +BASICBUILDS = libmimx-anthy.la +@WITH_GUI_FALSE@BUILD_LIBS = $(BASICBUILDS) +@WITH_GUI_TRUE@BUILD_LIBS = $(BASICBUILDS) libmimx-ispell.la +module_LTLIBRARIES = $(BUILD_LIBS) +libmimx_ispell_la_SOURCES = mimx-ispell.c +libmimx_ispell_la_LIBADD = ${common_ldflags_gui} +libmimx_ispell_la_LDFLAGS = -avoid-version -module +libmimx_anthy_la_SOURCES = mimx-anthy.c +libmimx_anthy_la_LIBADD = ${common_ldflags} @ANTHY_LD_FLAGS@ +libmimx_anthy_la_LDFLAGS = -avoid-version -module + +# Special targets to test the m17n library with Purify. +@MAINTAINER_MODE_TRUE@PURIFY = /usr/local/rational/releases/purify.sol.2002.05.00/purify +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu example/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu example/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-moduleLTLIBRARIES: $(module_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(module_LTLIBRARIES)'; test -n "$(moduledir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(moduledir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(moduledir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(moduledir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(moduledir)"; \ + } + +uninstall-moduleLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(module_LTLIBRARIES)'; test -n "$(moduledir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(moduledir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(moduledir)/$$f"; \ + done + +clean-moduleLTLIBRARIES: + -test -z "$(module_LTLIBRARIES)" || rm -f $(module_LTLIBRARIES) + @list='$(module_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libmimx-anthy.la: $(libmimx_anthy_la_OBJECTS) $(libmimx_anthy_la_DEPENDENCIES) $(EXTRA_libmimx_anthy_la_DEPENDENCIES) + $(AM_V_CCLD)$(libmimx_anthy_la_LINK) $(am_libmimx_anthy_la_rpath) $(libmimx_anthy_la_OBJECTS) $(libmimx_anthy_la_LIBADD) $(LIBS) + +libmimx-ispell.la: $(libmimx_ispell_la_OBJECTS) $(libmimx_ispell_la_DEPENDENCIES) $(EXTRA_libmimx_ispell_la_DEPENDENCIES) + $(AM_V_CCLD)$(libmimx_ispell_la_LINK) $(am_libmimx_ispell_la_rpath) $(libmimx_ispell_la_OBJECTS) $(libmimx_ispell_la_LIBADD) $(LIBS) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +m17n-conv$(EXEEXT): $(m17n_conv_OBJECTS) $(m17n_conv_DEPENDENCIES) $(EXTRA_m17n_conv_DEPENDENCIES) + @rm -f m17n-conv$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(m17n_conv_OBJECTS) $(m17n_conv_LDADD) $(LIBS) + +m17n-date$(EXEEXT): $(m17n_date_OBJECTS) $(m17n_date_DEPENDENCIES) $(EXTRA_m17n_date_DEPENDENCIES) + @rm -f m17n-date$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(m17n_date_OBJECTS) $(m17n_date_LDADD) $(LIBS) + +m17n-dump$(EXEEXT): $(m17n_dump_OBJECTS) $(m17n_dump_DEPENDENCIES) $(EXTRA_m17n_dump_DEPENDENCIES) + @rm -f m17n-dump$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(m17n_dump_OBJECTS) $(m17n_dump_LDADD) $(LIBS) + +m17n-edit$(EXEEXT): $(m17n_edit_OBJECTS) $(m17n_edit_DEPENDENCIES) $(EXTRA_m17n_edit_DEPENDENCIES) + @rm -f m17n-edit$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(m17n_edit_OBJECTS) $(m17n_edit_LDADD) $(LIBS) + +m17n-view$(EXEEXT): $(m17n_view_OBJECTS) $(m17n_view_DEPENDENCIES) $(EXTRA_m17n_view_DEPENDENCIES) + @rm -f m17n-view$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(m17n_view_OBJECTS) $(m17n_view_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mconv.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mdate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mdump.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/medit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mimx-anthy.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mimx-ispell.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mview.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(moduledir)" "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool \ + clean-moduleLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-moduleLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-moduleLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool \ + clean-moduleLTLIBRARIES cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-binPROGRAMS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-moduleLTLIBRARIES \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-moduleLTLIBRARIES + +.PRECIOUS: Makefile + + +@MAINTAINER_MODE_TRUE@purify_medit: medit ../src/.libs/libm17n-core.so ../src/.libs/libm17n.so ../src/.libs/libm17n-X.so linebreak.c +@MAINTAINER_MODE_TRUE@ ${PURIFY} gcc -g medit.o linebreak.o -lXaw -lXmu -L/usr/X11R6/lib -R/usr/X11R6/lib -lSM -lICE -lX11 -lXt -L../src/.libs -lm17n-core -lm17n -lm17n-X -ldl + +@MAINTAINER_MODE_TRUE@purify_mdate: mdate.o ../src/.libs/libm17n.so ../src/.libs/libm17n-X.so +@MAINTAINER_MODE_TRUE@ ${PURIFY} gcc -g mdate.o -lXaw -lXmu -L/usr/X11R6/lib -R/usr/X11R6/lib -lSM -lICE -lX11 -lXt -L../src/.libs -lm17n -lm17n-X -ldl + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/example/mconv.c b/example/mconv.c new file mode 100644 index 0000000..1104234 --- /dev/null +++ b/example/mconv.c @@ -0,0 +1,450 @@ +/* mconv.c -- Code converter. -*- coding: euc-jp; -*- + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @enpage m17n-conv convert file code + + @section m17n-conv-synopsis SYNOPSIS + + m17n-conv [ OPTION ... ] [ INFILE [ OUTFILE ] ] + + @section m17n-conv-description DESCRIPTION + + Convert encoding of given files from one to another. + + If INFILE is omitted, the input is taken from standard input. If + OUTFILE is omitted, the output written to standard output. + + The following OPTIONs are available. + +
    + +
  • -f FROMCODE + + FROMCODE is the encoding of INFILE (defaults to UTF-8). + +
  • -t TOCODE + + TOCODE is the encoding of OUTFILE (defaults to UTF-8). + +
  • -k + + Do not stop conversion on error. + +
  • -s + + Suppress warnings. + +
  • -v + + Print progress information. + +
  • -l + + List available encodings. + +
  • --version + + Print version number. + +
  • -h, --help + + Print this message. + +
+*/ +/***ja + @japage m17n-conv �ե�����Υ����ɤ��Ѵ����� + + @section m17n-conv-synopsis SYNOPSIS + + m17n-conv [ OPTION ... ] [ INFILE [ OUTFILE ] ] + + @section m17n-conv-description ���� + + Ϳ����줿�ե�����Υ����ɤ��̤Τ�Τ��Ѵ����롣 + + INFILE ����ά���줿���ϡ�ɸ�����Ϥ���Ȥ롣OUTFILE ����ά���줿 + ���ϡ�ɸ����Ϥؽ񤭽Ф��� + + �ʲ��Υ��ץ�������ѤǤ��롣 + +
    + +
  • -f FROMCODE + + FROMCODE �� INFILE �Υ����ɷϤǤ��롣(�ǥե���Ȥ� UTF-8) + +
  • -t TOCODE + + TOCODE �� OUTFILE �Υ����ɷϤǤ��롣(�ǥե���Ȥ� UTF-8) + +
  • -k + + ���顼���Ѵ�����ߤ��ʤ��� + +
  • -s + + �ٹ��ɽ�����ʤ��� + +
  • -v + + �ʹԾ�����ɽ�����롣 + +
  • -l + + ���Ѳ�ǽ�ʥ����ɷϤ���󤹤롣 + +
  • --version + + �С�������ֹ��ɽ�����롣 + +
  • -h, --help + + ���Υ�å�������ɽ�����롣 + +
+*/ + +#ifndef FOR_DOXYGEN + +#include +#include +#include + +#include +#include + +/* Print all coding system names. */ + +int +compare_coding_name (const void *elt1, const void *elt2) +{ + const MSymbol *n1 = elt1; + const MSymbol *n2 = elt2; + + return strcmp (msymbol_name (*n1), msymbol_name (*n2)); +} + +void +list_coding () +{ + MSymbol *codings; + int i, n; + char *name; + int len, clm; + + n = mconv_list_codings (&codings); + qsort (codings, n, sizeof (MSymbol), compare_coding_name); + clm = 0; + for (i = 0; i < n; i++) + { + name = msymbol_name (codings[i]); + len = strlen (name) + 1; + if (clm + len >= 80) + { + printf ("\n"); + clm = 0; + } + printf (" %s", name); + clm += len; + } + printf ("\n"); + free (codings); +} + + +/* Print the usage of this program (the name is PROG), and exit with + EXIT_CODE. */ + +void +help_exit (char *prog, int exit_code) +{ + char *p = prog; + + while (*p) + if (*p++ == '/') + prog = p; + + printf ("Usage: %s [ OPTION ... ] [ INFILE [ OUTFILE ] ]\n", prog); + printf ("Convert encoding of given files from one to another.\n"); + printf (" If INFILE is omitted, the input is taken from standard input.\n"); + printf (" If OUTFILE is omitted, the output is written to standard output.\n"); + printf ("The following OPTIONs are available.\n"); + printf (" %-13s %s", "-f FROMCODE", + "FROMCODE is the encoding of INFILE (defaults to UTF-8).\n"); + printf (" %-13s %s", "-t TOCODE", + "TOCODE is the encoding of OUTFILE (defaults to UTF-8).\n"); + printf (" %-13s %s", "-k", "Do not stop conversion on error.\n"); + printf (" %-13s %s", "-s", "Suppress warnings.\n"); + printf (" %-13s %s", "-v", "Print progress information.\n"); + printf (" %-13s %s", "-l", "List available encodings.\n"); + printf (" %-13s %s", "--version", "Print version number.\n"); + printf (" %-13s %s", "-h, --help", "Print this message.\n"); + exit (exit_code); +} + +/* Global flags to control the behaviour. */ +int suppress_warning; +int continue_on_error; + +/* Check invalid bytes found in the last decoding. Text property + Mcharset of such a byte is Mcharset_binary. */ + +void +check_invalid_bytes (MText *mt) +{ + int from = 0, to = 0; + int len = mtext_len (mt); + int first = 1; + + while (to < len) + { + int n = mtext_prop_range (mt, Mcharset, from, NULL, &to, 1); + MSymbol charset + = n > 0 ? (MSymbol) mtext_get_prop (mt, from, Mcharset) : Mnil; + + if (charset == Mcharset_binary) + { + if (! suppress_warning) + { + if (first) + { + fprintf (stderr, + "Invalid bytes (at each character position);\n"); + first = 0; + } + for (; from < to; from++) + fprintf (stderr, " 0x%02X(%d)", + mtext_ref_char (mt, from), from); + } + if (! continue_on_error) + { + if (! first) + fprintf (stderr, "\n"); + exit (1); + } + } + else + from = to; + } + if (! first) + fprintf (stderr, "\n"); +} + + +/* Check unencoded characters in the last encoding. Text property + Mcoding of such a character is Mnil. */ + +void +check_unencoded_chars (MText *mt, int len) +{ + int from = 0, to = 0; + int first = 1; + + while (to < len) + { + int n = mtext_prop_range (mt, Mcoding, from, NULL, &to, 1); + MSymbol coding + = n > 0 ? (MSymbol) mtext_get_prop (mt, from, Mcoding) : Mnil; + + if (coding == Mnil) + { + if (! suppress_warning) + { + if (first) + { + fprintf (stderr, + "Unencoded chars (at each character position):\n"); + first = 0; + } + for (; from < to; from++) + fprintf (stderr, " 0x%02X(%d)", + mtext_ref_char (mt, from), from); + } + if (! continue_on_error) + { + if (! first) + fprintf (stderr, "\n"); + exit (1); + } + } + else + from = to; + } + if (! first) + fprintf (stderr, "\n"); +} + + +void +unknown_encoding (char *name) +{ + if (! suppress_warning) + { + fprintf (stderr, "Unknown encoding: \"%s\"\n", name); + if (mconv_resolve_coding (msymbol ("iso-2022-jp")) == Mnil) + fprintf (stderr, "Perhaps the library \"m17n-db\" is missing.\n"); + } + exit (1); +} + +/* Format MSG by FMT and print the result to the stderr, and exit. */ + +#define FATAL_ERROR(fmt, arg) \ + do { \ + if (! suppress_warning) \ + fprintf (stderr, fmt, arg); \ + exit (1); \ + } while (0) + + +int +main (int argc, char **argv) +{ + int verbose; + MSymbol incode, outcode; + FILE *in, *out; + MText *mt; + MConverter *converter; + int i; + + /* Initialize the m17n library. */ + M17N_INIT (); + if (merror_code != MERROR_NONE) + FATAL_ERROR ("%s\n", "Fail to initialize the m17n library."); + + /* Default encodings are both UTF-8. */ + incode = outcode = Mcoding_utf_8; + /* By default, read from standard input and write to standard output. */ + in = stdin, out = stdout; + /* By default, all these flags are 0. */ + suppress_warning = verbose = continue_on_error = 0; + /* Parse the command line arguments. */ + for (i = 1; i < argc; i++) + { + if (! strcmp (argv[i], "--help") + || ! strcmp (argv[i], "-h") + || ! strcmp (argv[i], "-?")) + help_exit (argv[0], 0); + else if (! strcmp (argv[i], "--version")) + { + printf ("m17n-conv (m17n library) %s\n", M17NLIB_VERSION_NAME); + printf ("Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 AIST, JAPAN\n"); + exit (0); + } + else if (! strcmp (argv[i], "-l")) + { + list_coding (); + M17N_FINI (); + exit (0); + } + else if (! strcmp (argv[i], "-f") && i + 1 < argc) + { + incode = mconv_resolve_coding (msymbol (argv[++i])); + if (incode == Mnil) + unknown_encoding (argv[i]); + } + else if (! strcmp (argv[i], "-t") && i + 1 < argc) + { + outcode = mconv_resolve_coding (msymbol (argv[++i])); + if (outcode == Mnil) + unknown_encoding (argv[i]); + } + else if (! strcmp (argv[i], "-k")) + continue_on_error = 1; + else if (! strcmp (argv[i], "-s")) + suppress_warning = 1; + else if (! strcmp (argv[i], "-v")) + verbose = 1; + else if (argv[i][0] != '-') + { + if (in == stdin) + { + in = fopen (argv[i], "r"); + if (! in) + FATAL_ERROR ("Can't read the file %s\n", argv[i]); + } + else if (out == stdout) + { + out = fopen (argv[i], "w"); + if (! out) + FATAL_ERROR ("Can't write the file %s\n", argv[i]); + } + else + help_exit (argv[0], 1); + } + else + help_exit (argv[0], 1); + } + if (verbose) + suppress_warning = 0; + + /* Create an M-text to store the decoded characters. */ + mt = mtext (); + + /* Create a converter for decoding. */ + converter = mconv_stream_converter (incode, in); + if (! converter) + FATAL_ERROR ("Encoding \"%s\" requires the missing library \"m17n-db\".\n", + msymbol_name (incode)); + /* Instead of doing strict decoding, we decode all input bytes at + once, and check invalid bytes later by the fuction + check_invalid_bytes. */ + converter->lenient = 1; + + mconv_decode (converter, mt); + + check_invalid_bytes (mt); + if (verbose) + fprintf (stderr, "%d bytes (%s) decoded into %d characters,\n", + converter->nbytes, msymbol_name (incode), mtext_len (mt)); + + mconv_free_converter (converter); + + /* Create a converter for encoding. */ + converter = mconv_stream_converter (outcode, out); + if (! converter) + FATAL_ERROR ("Encoding \"%s\" requires the missing library \"m17n-db\".\n", + msymbol_name (outcode)); + /* Instead of doing strict encoding, we encode all characters at + once, and check unencoded characters later by the fuction + check_unencoded_chars. */ + converter->lenient = 1; + converter->last_block = 1; + if (mconv_encode (converter, mt) < 0 + && ! suppress_warning) + fprintf (stderr, "I/O error on writing\n"); + check_unencoded_chars (mt, converter->nchars); + if (verbose) + fprintf (stderr, "%d characters encoded into %d bytes (%s).\n", + converter->nchars, converter->nbytes, msymbol_name (outcode)); + + /* Clear away. */ + mconv_free_converter (converter); + fclose (in); + fclose (out); + m17n_object_unref (mt); + M17N_FINI (); + exit (0); +} +#endif /* not FOR_DOXYGEN */ diff --git a/example/mdate.c b/example/mdate.c new file mode 100644 index 0000000..d79ad56 --- /dev/null +++ b/example/mdate.c @@ -0,0 +1,238 @@ +/* mdate.c -- Show system date/time in all locales. -*- coding: euc-jp; -*- + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @enpage m17n-date display date and time + + @section m17n-date-synopsis SYNOPSIS + + m17n-date [ OPTION ... ] + + @section m17n-date-description DESCRIPTION + + Display the system date and time in many locales on a window. + + The following OPTIONs are available. + +
    + +
  • --version + + Print version number. + +
  • -h, --help + + Print this message. +
+*/ +/***ja + @japage m17n-date ������ɽ������ + + @section m17n-date-synopsis ���Υץ��� + + m17n-date [ OPTION ... ] + + @section m17n-date-description ���� + + �����ƥ�������򤵤ޤ��ޤʥ�������ǥ�����ɥ���ɽ�����롣 + + �ʲ��Υ��ץ�������ѤǤ��롣 + +
    + +
  • --version + + �С�������ֹ��ɽ�����롣 + +
  • -h, --help + + ���Υ�å�������ɽ�����롣 + +
+*/ + +#ifndef FOR_DOXYGEN + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Return a plist of all locales currently avairable on the system. + The keys and values of the plist are locale name symbols and + pointers to MLocale respectively. */ + +MPlist * +list_system_locales () +{ + FILE *p; + char buf[1024]; + MPlist *plist; + + /* Run the command "locale -a" to get a list of locales. */ + if (! (p = popen ("locale -a", "r"))) + { + fprintf (stderr, "Can't run `locale -a'.\n"); + exit (1); + } + + plist = mplist (); + /* Read from the pipe one line by one. */ + while (fgets (buf, 1024, p)) + { + MLocale *locale; + int len = strlen (buf); + + if (buf[len - 1] == '\n') + buf[len - 1] = '\0'; + locale = mlocale_set (LC_TIME, buf); + + /* If the locale is surely usable, it is not duplicated, and we + know the corresponding coding system, add it to the list. */ + if (locale + && ! mplist_get (plist, mlocale_get_prop (locale, Mname)) + && mlocale_get_prop (locale, Mcoding) != Mnil) + mplist_add (plist, mlocale_get_prop (locale, Mname), locale); + } + pclose (p); + return plist; +} + + +/* Print the usage of this program (the name is PROG), and exit with + EXIT_CODE. */ + +void +help_exit (char *prog, int exit_code) +{ + char *p = prog; + + while (*p) + if (*p++ == '/') + prog = p; + + printf ("Usage: %s [ OPTION ...]\n", prog); + printf ("Display the system date and time in many locales on a window.\n"); + printf ("The following OPTIONs are available.\n"); + printf (" %-13s %s", "--version", "Print version number.\n"); + printf (" %-13s %s", "-h, --help", "Print this message.\n"); + exit (exit_code); +} + + +/* Format MSG by FMT and print the result to the stderr, and exit. */ + +#define FATAL_ERROR(fmt, arg) \ + do { \ + fprintf (stderr, fmt, arg); \ + exit (1); \ + } while (0) + + +int +main (int argc, char **argv) +{ + time_t current_time_t = time (NULL); + struct tm *current_time_tm = localtime (¤t_time_t); + /* List of all locales. */ + MPlist *locale_list, *plist; + /* Text to be shown. */ + MText *mt; + int i; + + for (i = 1; i < argc; i++) + { + if (! strcmp (argv[i], "--help") + || ! strcmp (argv[i], "-h") + || ! strcmp (argv[i], "-?")) + help_exit (argv[0], 0); + else if (! strcmp (argv[i], "--version")) + { + printf ("m17n-date (m17n library) %s\n", M17NLIB_VERSION_NAME); + printf ("Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 AIST, JAPAN\n"); + exit (0); + } + else + help_exit (argv[0], 1); + } + + + /* Initialize the m17n library. */ + M17N_INIT (); + if (merror_code != MERROR_NONE) + FATAL_ERROR ("%s\n", "Fail to initialize the m17n library."); + + /* Get a locale list in LOCALE_LIST, and generate an M-text that + contains date string in each locale. */ + locale_list = list_system_locales (); + mt = mtext (); + plist = locale_list; + while (mplist_key (plist) != Mnil) + { + char *name = msymbol_name (mplist_key (plist)); + char fmtbuf[256]; + int len; + MLocale *locale = mplist_value (plist); + MSymbol coding = mlocale_get_prop (locale, Mcoding); + /* One line text for this locale. The format is: + "LOCALE-NAME: DATE-AND-TIME-STRING". */ + MText *thisline; + + sprintf (fmtbuf, "%16s: ", name); + len = strlen (fmtbuf); + thisline = mconv_decode_buffer (coding, (unsigned char *) fmtbuf, len); + if (thisline) + { + mlocale_set (LC_TIME, name); + if (mtext_ftime (thisline, "%c", current_time_tm, NULL) > 0) + { + mtext_cat_char (thisline, '\n'); + mtext_cat (mt, thisline); + } + m17n_object_unref (thisline); + } + plist = mplist_next (plist); + } + + /* Show the generated M-text by another example program "mview". */ + { + FILE *p = popen ("m17n-view", "w"); + + if (!p) + FATAL_ERROR ("%s\n", "Can't run the program mview!"); + mconv_encode_stream (Mcoding_utf_8, mt, p); + fclose (p); + } + + /* Clear away. */ + m17n_object_unref (locale_list); + m17n_object_unref (mt); + M17N_FINI (); + + exit (0); +} +#endif /* not FOR_DOXYGEN */ diff --git a/example/mdump.c b/example/mdump.c new file mode 100644 index 0000000..5cb3dc7 --- /dev/null +++ b/example/mdump.c @@ -0,0 +1,810 @@ +/* mdump.c -- Dump text image -*- coding: euc-jp; -*- + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @enpage m17n-dump dump text image + + @section m17n-dump-synopsis SYNOPSIS + + m17n-dump [ OPTION ... ] [ FILE ] + + @section m17n-dump-description DESCRIPTION + + Dump a text as PNG image file. + + The PNG file is written to a file created in the current directory + with the name "BASE.png" where BASE is the basename of FILE. If + FILE is omitted, text is read from standard input, and the image + is dumped into the file "output.png". + + The following OPTIONs are available. + +
    + +
  • -s SIZE + + SIZE is the font size in point. The default font size is 12 point. + +
  • -d DPI + + DPI is the resolution in dots per inch. The default resolution is + 300 dpi. + +
  • -p PAPER + + PAPER is the paper size: a4, a4r, a5, a5r, b5, b5r, letter, WxH, + or W. In the case of WxH, W and H are the width and height in + millimeter. In the case of W, W is the width in millimeter. If + this option is specified, PAPER limits the image size. If FILE is + too large for a single page, multiple files with the names + "BASE.01.png", "BASE.02.png", etc. are created. + +
  • -m MARGIN + + MARGIN is the horizontal and vertical margin in millimeter. The + default margin is 20 mm. It is ignored when PAPER is not + specified. + +
  • -c POS + + POS is the character position of cursor to draw. By default, + cursor is not drawn. + +
  • -x + + FILE is assumed to be an XML file generated by the serialize + facility of the m17n library, and FILE is deserialized before an + image is created. + +
  • -w + + Each line is broken at word boundary. + +
  • -f FILTER + + FILTER is a string containing a shell command line. If this + option is specified, the PNG image is not written info a + file but is given to FILTER as standard input. If FILTER + contains "%s", that part is replaced by a basename of FILE. + So, the default behaviour is the same as specifying "cat > + %s.png" as FILTER. + + If FILTER is just "-", the PNG image is written to stdout. + +
  • -a + + Enable anti-alias drawing. + +
  • --family FAMILY + + Prefer a font whose family name is FAMILY. + +
  • --language LANG + + Prefer a font specified for the language LANG. LANG must be a + 2-letter code of ISO 630 (e.g. "en" for English). + +
  • -fg FOREGROUND + + Specify the text color. The supported color names are those of + HTML 4.0 and "#RRGGBB" notation. + +
  • -bg BACKGROUND + + Specify the background color. The supported color names are the + same as FOREGROUND, except that if "transparent" is specified, + make the background transparent. + +
  • -r + + Specify that the orientation of the text is right-to-left. + +
  • -q + + Quiet mode. Don't print any messages. + +
  • --version + + Print the version number. + +
  • -h, --help + + Print this message. + +
+*/ +/***ja + @japage m17n-dump �ƥ����Ȳ����Υ���� + + @section m17n-dump-synopsis SYNOPSIS + + m17n-dump [ OPTION ... ] [ FILE ] + + @section m17n-dump-description DESCRIPTION + + �ƥ����Ȥ� PNG �����Ȥ��ƥ���פ��롣 + + PNG �����ϸ��ߤΥǥ��쥯�ȥ�˺��줿 "BASE.png" �Ȥ���̾���� + �ե�����˽񤭹��ޤ�롣������ BASE ��FILE �� basename �Ǥ��롣 + FILE ����ά�����С��ƥ����Ȥ�ɸ�����Ϥ����ɤޤ졢������ + "output.png" �˥���פ���롣 + + �ʲ��Υ��ץ�������ѤǤ��롣 + +
    + +
  • -s SIZE + + SIZE �ϥե���Ȥ��礭����ݥ����ñ�̤Ǽ�������ΤǤ��롣�ǥե��� + �Ȥ��礭���� 12 �ݥ���ȡ� + +
  • -d DPI + + DPI �ϲ����٤򣱥����������Υɥå�ñ�̤Ǽ�������ΤǤ��롣�ǥե� + ��Ȥβ����٤� 300 dpi�� + +
  • -p PAPER + + PAPER �Ϥڡ��ѥ����� : a4, a4r, a5, a5r, b5, b5r, letter, WxH �ޤ� + �� W�� WxH �ξ�硢 W �� H �����ȹ⤵��ߥ�᡼��ñ�̤Ǽ�������Ρ� + W �ξ�硢 W ������ߥ�᡼��ñ�̤Ǽ�������Ρ����Υ��ץ���󤬻��� + ����Ƥ�����ϡ� PAPER �����������������¤� �롣FILE �� 1 �ڡ��� + ��Ǽ�ޤ�ʤ��ۤ��礭�����ϡ�"BASE.01.png", "BASE.02.png" ����̾�� + �ΤĤ���ʣ���Υե����뤬����롣 + +
  • -m MARGIN + + MARGIN �Ͽ�ʿ����ľ�ޡ������ߥ�᡼��ñ�̤Ǽ�������ΤǤ��롣�� + �ե���ȤΥޡ������ 20 mm��PAPER �����ꤵ��Ƥ��ʤ����̵�뤵��롣 + +
  • -c POS + + POS �ϥ��������ʸ�����֡��ǥե���ȤǤϡ����������������ʤ��� + +
  • -x + + FILE �� m17n �饤�֥��Υ��ꥢ�饤����ǽ�ˤ�äƺ��줿 XML �ե� + ����Ǥ��ꡢ�����������������˥ǥ��ꥢ�饤������롣 + +
  • -w + + ��ζ����Dz��Ԥ��롣 + +
  • -f FILTER + + FILTER �ϥ����륳�ޥ�ɹԤ�ޤ�ʸ����Ǥ��롣���Υ��ץ���󤬻��� + ����Ƥ���С�PNG �����ϥե�����˽񤫤��ΤǤϤʤ���FILTER �� + ɸ�����ϤȤ����Ϥ���롣 FILTER �� "%s" ��ޤ�Ǥ���С������ FILE + �Υ١����͡�����֤��������롣���Υץ������Υǥե���Ȥο��� + �ȡ�FILTER �� "cat > %s.png" ����ꤷ�����ο����Ʊ��Ǥ��롣 + + �⤷ FILTER ��ñ�� "-" �Ǥ���С� PNG ������ stdout �˽��Ϥ���롣 + +
  • -a + + ����������ꥢ��������Ԥ��� + +
  • --family FAMILY + + �ե��ߥꥣ̾�� FAMILY �Υե���Ȥ�ͥ��Ū�˻Ȥ��� + +
  • --language LANG + + ���� LANG �Ѥ˻��ꤵ�줿�ե���Ȥ�ͥ��Ū�˻Ȥ���LANG �� ISO 630 �� + ��ʸ�������ɡ��㡧�Ѹ�� "en" �ˤǤʤ���Фʤ�ʤ��� + +
  • -fg FOREGROUND + + �ƥ����Ȥο�����ꤹ�롣HTML 4.0 �ο���̾������� "#RRGGBB" ��ˡ�� + ���ݡ��ȡ� + +
  • -bg BACKGROUND + + �طʤο�����ꤹ�롣���ݡ��Ȥ���Ƥ��뿧��̾���� FOREGROUND Ʊ���� + ���������⤷ "transparent" �����ꤵ�줿���طʤ�Ʃ���ˤ��롣 + +
  • -r + + Specify that the orientation of the text is right-to-left. + +
  • -q + + ���ڤΥ�å�������ɽ�����ʤ��� + +
  • --version + + �С�������ֹ��ɽ�����롣 + +
  • -h, --help + + ���Υ�å�������ɽ�����롣 + +
+*/ + +#ifndef FOR_DOXYGEN + +#include +#include +#include +#include +#include + +#if defined (HAVE_FREETYPE) && defined (HAVE_GD) +#include + +#include +#include + +/* Enumuration of the supported paper types. */ +enum paper_type + { + PAPER_A4, + PAPER_A4R, + PAPER_A5, + PAPER_A5R, + PAPER_B5, + PAPER_B5R, + PAPER_LETTER, + PAPER_USER, + PAPER_NOLIMIT + }; + +/* Array of paper sizes for the supported paper types. */ +struct +{ + int width, height; /* in millimeter */ +} paper_size[PAPER_NOLIMIT] = { + { 210, 297 }, /* a4 */ + { 297, 210 }, /* a4r */ + { 148, 210 }, /* a5 */ + { 210, 148 }, /* a5r */ + { 250, 176 }, /* b5 */ + { 176, 250 }, /* b5r */ + { 216, 279 }, /* letter */ +}; + + +/* Print the usage of this program (the name is PROG), and exit with + EXIT_CODE. */ + +void +help_exit (char *prog, int exit_code) +{ + char *p = prog; + + while (*p) + if (*p++ == '/') + prog = p; + + printf ("Usage: %s [ OPTION ...] [ FILE ]\n", prog); + printf ("Dump a text as a PNG image into a file.\n"); + printf (" The PNG file is created in the current directory\n"); + printf (" with the name \"BASE.png\" where BASE is the basename of FILE.\n"); + printf (" If FILE is omitted, text is read from standard input, and\n"); + printf (" dumped into the file \"output.png\".\n"); + printf ("The following OPTIONs are available.\n"); + printf (" %-13s %s", "-s SIZE", + "Font size in 1/10 point (default 120).\n"); + printf (" %-13s %s", "-d DPI", + "Resolution in dots per inch (defualt 300).\n"); + printf (" %-13s %s", "-p PAPER", + "Paper size; a4, a4r, a5, a5r, b5, b5r, letter, W, or WxH.\n"); + printf (" %-13s %s", "-m MARGIN", + "Marginal space in millimeter (default 20).\n"); + printf (" %-13s %s", "-c POS", + "Character position of cursor to draw (default no cursor)\n"); + printf (" %-13s %s", "-x", + "FILE is assumed to be an XML file.\n"); + printf (" %-13s %s", "-f FILTER", + "String containing a shell command line to be used as a filter.\n"); + printf (" %-13s %s", "-w", "Each line is broken at word boundary.\n"); + printf (" %-13s %s", "-a", "Enable anti-alias drawing.\n"); + printf (" %-13s %s", "--family FAMILY", + "Prefer a font whose family is FAMILY.\n"); + printf (" %-13s %s", "--language LANG", + "Prefer a font specified for the language LANG.\n"); + printf (" %-13s %s", "-r", + "Specify that the orientation of the text is right-to-left.\n"); + printf (" %-13s %s", "-fg FOREGROUND", + "Specify the text color (HTML 4.0 color names or \"#RRGGBB\").\n"); + printf (" %-13s %s", "-bg BACKGROUND", + "Specify the background color (\"transparent\" for transparent)\n"); + printf (" %-13s %s", "-q", "Quiet mode. Don't print any messages.\n"); + printf (" %-13s %s", "--version", "Print the version number.\n"); + printf (" %-13s %s", "-h, --help", "Print this message.\n"); + exit (exit_code); +} + + +/* Format MSG by FMT and print the result to the stderr, and exit. */ + +#define FATAL_ERROR(fmt, arg) \ + do { \ + fprintf (stderr, fmt, arg); \ + exit (1); \ + } while (0) + + +/* Move POS to the next line head in M-text MT whose length is LEN. + If POS is already on the last line, set POS to LEN. */ + +#define NEXTLINE(pos, len) \ + do { \ + pos = mtext_character (mt, pos, len, '\n'); \ + if (pos < 0) \ + pos = len; \ + else \ + pos++; \ + } while (0) + + +/* Find the range of M-text MT that fits in one page of height HEIGHT + when drawn from the character position POS. Set RECT->y to the + Y-offset of the first baseline. */ + +int +find_page_end (MFrame *frame, int height, MText *mt, int pos, + MDrawControl *control, MDrawMetric *rect) +{ + int len = mtext_len (mt); + int to = pos; + int y = 0, yoff; + + while (to < len) + { + int next = to; + + NEXTLINE (next, len); + mdraw_text_extents (frame, mt, to, next, control, NULL, NULL, rect); + if (to == pos) + yoff = rect->y; + if (y + rect->height > height) + { + MDrawGlyphInfo info; + + while (to < next) + { + mdraw_glyph_info (frame, mt, to, to, control, &info); + if (y + info.metrics.height > height) + break; + y += info.metrics.height; + to = info.line_to; + } + break; + } + y += rect->height; + to = next; + } + + rect->y = yoff; + return to; +} + +/* Dump the image in IMAGE into a file whose name is generated from + FILENAME and PAGE_INDEX (if it is not zero). */ + +void +dump_image (gdImagePtr image, char *filename, char *filter, + int page_index, int quiet_mode) +{ + FILE *fp; + + if (page_index) + { + char *name = alloca (strlen (filename) + 8); + + sprintf (name, "%s.%02d", filename, page_index); + filename = name; + } + + if (filter) + { + if (filter[0] == '-' && filter[1] == '\0') + fp = stdout; + else + { + char *command = alloca (strlen (filename) + strlen (filter) + 1); + + sprintf (command, filter, filename); + fp = popen (command, "w"); + if (! fp) + FATAL_ERROR ("Can't run the command \"%s\"\n", command); + if (! quiet_mode) + printf ("Running \"%s\" ... ", command); + } + } + else + { + char *fullname = alloca (strlen (filename) + 5); + + sprintf (fullname, "%s.png", filename); + fp = fopen (fullname, "w"); + if (! fp) + FATAL_ERROR ("Can't write to \"%s\"\n", fullname); + if (! quiet_mode) + printf ("Writing %s ... ", fullname); + } + + /* Generate PNG. */ + gdImagePng (image, fp); + if (fp != stderr) + fclose (fp); + if (! quiet_mode) + printf (" done (%dx%d)\n", image->sx, image->sy); +} + +extern int line_break (MText *mt, int pos, int from, int to, int line, int y); + +int +main (int argc, char **argv) +{ + int fontsize = 120; + int paper = PAPER_NOLIMIT; + int dpi = 300; + int margin = 20; + int xml = 0; + FILE *fp = stdin; + int cursor_pos = -1; + int quiet_mode = 0; + int break_by_word = 0; + char *filter = NULL; + int paper_width, paper_height; + int anti_alias = 0; + char *family_name = NULL; + char *lang_name = NULL; + char *fg_color = NULL, *bg_color = NULL; + int transparent = 0; + int r2l = 0; + int i; + int page_index; + gdImagePtr image; + int bg_rgb; + + MFrame *frame; + MText *mt; + MDrawControl control; + MDrawMetric rect; + char *filename = "output"; + int len, from; + char *fontset_name = "generic"; + + + /* Parse the command line arguments. */ + for (i = 1; i < argc; i++) + { + if (! strcmp (argv[i], "--help") + || ! strcmp (argv[i], "-h") + || ! strcmp (argv[i], "-?")) + help_exit (argv[0], 0); + else if (! strcmp (argv[i], "--version")) + { + printf ("m17n-dump (m17n library) %s\n", M17NLIB_VERSION_NAME); + printf ("Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 AIST, JAPAN\n"); + exit (0); + } + else if (! strcmp (argv[i], "-s") && i + 1< argc) + { + fontsize = atoi (argv[++i]); + if (! fontsize) + FATAL_ERROR ("Invalid font size: %s\n", argv[i]); + } + else if (! strcmp (argv[i], "-p") && i + 1< argc) + { + int w, h; + + i++; + if (! strcmp (argv[i], "a4")) + paper = PAPER_A4; + else if (! strcmp (argv[i], "a4r")) + paper = PAPER_A4R; + else if (! strcmp (argv[i], "a5")) + paper = PAPER_A5; + else if (! strcmp (argv[i], "a5r")) + paper = PAPER_A5R; + else if (! strcmp (argv[i], "b5")) + paper = PAPER_B5; + else if (! strcmp (argv[i], "b5r")) + paper = PAPER_B5R; + else if (! strcmp (argv[i], "letter")) + paper = PAPER_LETTER; + else if (sscanf (argv[i], "%dx%d", &w, &h) == 2 + && w > 0 && h > 0) + { + paper = PAPER_USER; + paper_size[paper].width = w; + paper_size[paper].height = h; + } + else if (sscanf (argv[i], "%d", &w) == 1 + && w > 0) + { + paper = PAPER_USER; + paper_size[paper].width = w; + paper_size[paper].height = 0; + } + else + FATAL_ERROR ("Invalid paper type: %s\n", argv[i]); + } + else if (! strcmp (argv[i], "-d") && i + 1< argc) + { + dpi = atoi (argv[++i]); + if (! dpi) + FATAL_ERROR ("Invalid resolution: %s\n", argv[i]); + } + else if (! strcmp (argv[i], "-m") && i + 1< argc) + { + margin = atoi (argv[++i]); + if (margin < 0) + FATAL_ERROR ("Invalid margin: %s\n", argv[i]); + } + else if (! strcmp (argv[i], "-c") && i + 1< argc) + { + cursor_pos = atoi (argv[++i]); + if (cursor_pos < 0) + FATAL_ERROR ("Invalid cursor position: %s\n", argv[i]); + } + else if (! strcmp (argv[i], "-f") && i + 1< argc) + { + filter = argv[++i]; + } + else if (! strcmp (argv[i], "-x")) + { + xml = 1; + } + else if (! strcmp (argv[i], "-w")) + { + break_by_word = 1; + } + else if (! strcmp (argv[i], "-q")) + { + quiet_mode = 1; + } + else if (! strcmp (argv[i], "-a")) + { + anti_alias = 1; + } + else if (! strcmp (argv[i], "--family")) + { + family_name = argv[++i]; + } + else if (! strcmp (argv[i], "--language")) + { + lang_name = argv[++i]; + } + else if (! strcmp (argv[i], "-r")) + { + r2l = 1; + } + else if (argv[i][0] != '-') + { + fp = fopen (argv[i], "r"); + if (! fp) + FATAL_ERROR ("Fail to open the file %s!\n", argv[i]); + filename = basename (argv[i]); + } + else if (! strcmp (argv[i], "--fontset")) + { + fontset_name = argv[++i]; + } + else if (! strcmp (argv[i], "-fg")) + { + if (i + 1 == argc) + { + fprintf (stderr, "Foreground color not specified\n"); + help_exit (argv[0], 1); + } + fg_color = argv[++i]; + } + else if (! strcmp (argv[i], "-bg")) + { + if (i + 1 == argc) + { + fprintf (stderr, "Background color not specified\n"); + help_exit (argv[0], 1); + } + i++; + if (! strcmp (argv[i], "transparent")) + transparent = 1; + else + bg_color = argv[i]; + } + else + { + fprintf (stderr, "Unknown or invalid option: %s\n", argv[i]); + help_exit (argv[0], 1); + } + } + + /* Initialize the m17n library. */ + M17N_INIT (); + if (merror_code != MERROR_NONE) + FATAL_ERROR ("%s\n", "Fail to initialize the m17n library."); + + mt = mconv_decode_stream (Mcoding_utf_8, fp); + fclose (fp); + if (xml) + mt = mtext_deserialize (mt); + if (! mt) + FATAL_ERROR ("%s\n", "Fail to decode the input file or stream!"); + + len = mtext_len (mt); + if (lang_name) + mtext_put_prop (mt, 0, len, Mlanguage, msymbol (lang_name)); + + if (paper == PAPER_NOLIMIT) + paper_width = paper_height = margin = 0; + else + { + paper_width = paper_size[paper].width * dpi / 25.4; + paper_height = paper_size[paper].height * dpi / 25.4; + margin = margin * dpi / 25.4; + } + + { + MPlist *plist = mplist (), *p; + MFontset *fontset = mfontset (fontset_name); + MFace *face = mface (); + + mface_put_prop (face, Mfontset, fontset); + mface_put_prop (face, Msize, (void *) (fontsize * dpi / 100)); + if (family_name) + { + char *p; + + for (p = family_name; *p; p++) + if (isupper (*p)) *p = tolower (*p); + mface_put_prop (face, Mfamily, msymbol (family_name)); + } + if (fg_color) + mface_put_prop (face, Mforeground, msymbol (fg_color)); + if (bg_color) + mface_put_prop (face, Mbackground, msymbol (bg_color)); + p = mplist_add (plist, Mdevice, msymbol ("gd")); + p = mplist_add (p, Mface, face); + m17n_object_unref (face); + frame = mframe (plist); + m17n_object_unref (plist); + if (! frame) + FATAL_ERROR ("%s\n", "Can't open a frame (perhaps no font available)!"); + } + + memset (&control, 0, sizeof control); + control.two_dimensional = 1; + control.enable_bidi = 1; + control.anti_alias = anti_alias; + control.orientation_reversed = r2l; + if (cursor_pos >= 0) + { + control.with_cursor = 1; + if (cursor_pos > len) + cursor_pos = len; + control.cursor_pos = cursor_pos; + control.cursor_width = -1; + } + else + control.ignore_formatting_char = 1; + if (break_by_word) + control.line_break = mdraw_default_line_break; + + if (paper == PAPER_NOLIMIT) + { + control.max_line_width = 0; + mdraw_text_extents (frame, mt, 0, len, &control, NULL, NULL, &rect); + paper_width = rect.width; + paper_height = rect.height; + } + else + { + control.max_line_width = paper_width - margin * 2; + if (paper_height == 0) + { + mdraw_text_extents (frame, mt, 0, len, &control, NULL, NULL, &rect); + paper_height = rect.height + margin * 2; + } + } + +#if HAVE_GD > 1 + image = gdImageCreateTrueColor (paper_width, paper_height); +#else + image = gdImageCreate (paper_width, paper_height); +#endif + from = 0; + page_index = 1; + + if (transparent) + { + MFace *face = mframe_get_prop (frame, Mface); + MSymbol fg = mface_get_prop (face, Mforeground); + int rgb_value = 0; + + if (fg) + rgb_value = (int) msymbol_get (fg, msymbol (" rgb")); + if (rgb_value == 0xFFFFFF) + bg_rgb = gdImageColorAllocate (image, 0, 0, 0); + else + bg_rgb = gdImageColorAllocate (image, 255, 255, 255); + gdImageColorTransparent (image, bg_rgb); +#if HAVE_GD > 1 + gdImageAlphaBlending (image, 0); +#endif + } + else + { + MFace *face = mframe_get_prop (frame, Mface); + MSymbol bg = mface_get_prop (face, Mbackground); + if (bg) + { + int rgb_value = (int) msymbol_get (bg, msymbol (" rgb")); + bg_rgb = gdImageColorAllocate (image, rgb_value >> 16, + (rgb_value >> 8) & 255, + rgb_value & 255); + } + else + bg_rgb = gdImageColorAllocate (image, 255, 255, 255); + } + + while (from < len) + { + int to; + + if (paper == PAPER_NOLIMIT || paper_size[paper].height == 0) + to = len; + else + to = find_page_end (frame, paper_height - margin * 2, mt, from, + &control, &rect); + + gdImageFilledRectangle (image, 0, 0, paper_width - 1, paper_height - 1, + bg_rgb); + if (! r2l) + mdraw_text_with_control (frame, image, + margin, margin - rect.y, + mt, from, to, &control); + else + mdraw_text_with_control (frame, image, + paper_width - margin, margin - rect.y, + mt, from, to, &control); + dump_image (image, filename, filter, + ((from > 0 || to < len) ? page_index : 0), + quiet_mode); + + from = to; + page_index++; + } + + m17n_object_unref (frame); + m17n_object_unref (mt); + M17N_FINI (); + gdImageDestroy (image); + exit (0); +} + +#else /* not HAVE_FREETYPE nor HAVE_GD */ + +int +main (int argc, char **argv) +{ + fprintf (stderr, "Can't run without Freetype and GD library!\n"); + exit (1); +} + +#endif /* not HAVE_FREETYPE nor HAVE_GD */ +#endif /* not FOR_DOXYGEN */ diff --git a/example/medit.c b/example/medit.c new file mode 100644 index 0000000..e6a6dc8 --- /dev/null +++ b/example/medit.c @@ -0,0 +1,3278 @@ +/* medit.c -- simple multilingual editor. -*- coding: euc-jp; -*- + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @enpage m17n-edit edit multilingual text + + @section m17n-edit-synopsis SYNOPSIS + + m17n-edit [ XT-OPTION ...] [ OPTION ... ] FILE + + @section m17n-edit-description DESCRIPTION + + Display FILE on a window and allow users to edit it. + + XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg). + + The following OPTIONs are available. + +
    + +
  • --version + + Print version number. + +
  • -h, --help + + Print this message. + +
+ + This program is to demonstrate how to use the m17n GUI API. + Although m17n-edit directly uses the GUI API, the API is mainly + for toolkit libraries or to implement XOM (X Output Method), not + for direct use from application programs. +*/ +/***ja + @japage m17n-edit ¿����ƥ����Ȥ��Խ� + + @section m17n-edit-synopsis SYNOPSIS + + m17n-edit [ XT-OPTION ...] [ OPTION ... ] FILE + + @section m17n-edit-description DESCRIPTION + + FILE �򥦥���ɥ���ɽ�������桼�����Խ��Ǥ���褦�ˤ��롣 + + XT-OPTIONs �� Xt ��ɸ��ΰ����Ǥ��롣 (e.g. -fn, -fg). + + �ʲ��Υ��ץ�������ѤǤ��롣 + +
    + +
  • --version + + �С�������ֹ��ɽ�����롣 + +
  • -h, --help + + ���Υ�å�������ɽ�����롣 + +
+ + ���Υץ������� m17n GUI API �λȤ����򼨤���ΤǤ��롣m17n-edit + ��ľ�� GUI API ��ȤäƤ��뤬������ API �ϼ�˥ġ��륭�åȥ饤�֥� + ���XOM (X Output Method) �μ����ѤǤ��ꡢ���ץꥱ�������ץ����� + �फ���ľ�ܤ����Ѥ�տޤ��Ƥ��ʤ��� +*/ + +#ifndef FOR_DOXYGEN + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_X11_XAW_COMMAND_H + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Global variables. */ + +char *filename; +int serialized; + +/* For the X Window System. */ +Display *display; +int screen; +/* GCs for normal drawing, filling by background color, normal drawing + on bitmap (i.e. pixmap of depth 1), filling bitmap by background + color. */ +GC gc, gc_inv, mono_gc, mono_gc_inv; +Window win; +Atom XA_TEXT, XA_COMPOUND_TEXT, XA_UTF8_STRING; /* X Selection types. */ +XtAppContext context; +int default_font_size; + +/* Widget hierarchy + +Shell - Form -+- Head -- File, Cursor, Bidi, LineBreak, InputMethod, CurIM; + +- Face -- Size, Family, Style, Color, Misc, Pop, CurFace + +- Lang -- A-B, C-D, ..., U-Z, Pop, CurLang + +- Body -- Sbar, Text + +- Tail -- Message +*/ + +Widget ShellWidget, HeadWidget, TailWidget, MessageWidget; +Widget CursorMenus[5], BidiMenus[3], LineBreakMenus[3], *InputMethodMenus; +Widget SbarWidget, TextWidget; +Widget FileShellWidget, FileDialogWidget; +Widget FaceWidget, CurFaceWidget, LangWidget, CurLangWidget; +Widget CurIMLang, CurIMStatus; + +int win_width, win_height; /* Size of TextWidget. */ +Arg arg[10]; + +Pixmap input_status_pixmap; +int input_status_width, input_status_height; + +/* Bitmap for "check" glyph. */ +#define check_width 9 +#define check_height 8 +static unsigned char check_bits[] = { + 0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, + 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00 }; +Pixmap CheckPixmap; + +/* For the m17n library. */ +MFrame *frame; +MText *mt; +int nchars; /* == mtext_len (mt) */ +int mt_modified; +MDrawControl control, input_status_control; +MTextProperty *selection; + +MSymbol Mword; + +MFace *face_default; +MFace *face_xxx_large; +MFace *face_box; +MFace *face_courier, *face_helvetica, *face_times; +MFace *face_dv_ttyogesh, *face_freesans, *face_freeserif, *face_freemono; +MFace *face_default_fontset, *face_no_ctl_fontset; +MFace *face_input_status; + +MSymbol Mcoding_compound_text; + +int logical_move = 1; /* If 0, move cursor visually. */ + +typedef struct { + int available; + MSymbol language, name; + MInputMethod *im; +} InputMethodInfo; + +InputMethodInfo *input_method_table; + +int num_input_methods; +int current_input_method = -1; /* i.e. none */ +int unicode_input_method = -1; +int auto_input_method = 0; +int saved_input_method = -3; +MInputContext *current_input_context; + +struct FaceRec +{ + char *name; + MFace **face; +} face_table[] = + { {"Menu Size", NULL}, + {"xx-small", &mface_xx_small}, + {"x-small", &mface_x_small}, + {"small", &mface_small}, + {"normalsize", &mface_normalsize}, + {"large", &mface_large}, + {"x-large", &mface_x_large}, + {"xx-large", &mface_xx_large}, + {"xxx-large", &face_xxx_large}, + + {"Menu Family", NULL}, + {"courier", &face_courier}, + {"helvetica", &face_helvetica}, + {"times", &face_times}, + {"dv-ttyogesh", &face_dv_ttyogesh}, + {"freesans", &face_freesans}, + {"freeserif", &face_freeserif}, + {"freemono", &face_freemono}, + + {"Menu Style", NULL}, + {"medium", &mface_medium}, + {"bold", &mface_bold}, + {"italic", &mface_italic}, + + {"Menu Color", NULL}, + {"black", &mface_black}, + {"white", &mface_white}, + {"red", &mface_red}, + {"green", &mface_green}, + {"blue", &mface_blue}, + {"cyan", &mface_cyan}, + {"yello", &mface_yellow}, + {"magenta", &mface_magenta}, + + {"Menu Misc", NULL}, + {"normal", &mface_normal_video}, + {"reverse", &mface_reverse_video}, + {"underline", &mface_underline}, + {"box", &face_box}, + {"No CTL", &face_no_ctl_fontset} }; + + +int num_faces = sizeof (face_table) / sizeof (struct FaceRec); + +/* Information about a physical line metric. */ +struct LineInfo +{ + int from; /* BOL position of the line. */ + int to; /* BOL position of the next line. */ + int y0, y1; /* Top and bottom Y position of the line. */ + int ascent; /* Height of the top Y position. */ +}; + +struct LineInfo top; /* Topmost line. */ +struct LineInfo cur; /* Line containing cursor. */ +struct LineInfo sel_start; /* Line containing selection start. */ +struct LineInfo sel_end; /* Line containing selection end. */ + +MDrawGlyphInfo cursor; /* Information about the cursor glyph. */ + +/* X position to keep on vertical (up and down) cursor motion. */ +int target_x_position; + +/* Interface macros for m17n-lib drawing routines. */ + +/* Draw a text in the range $FROM to $TO of the M-text #MT at the + coordinate ($X, $Y) */ +#define DRAW_TEXT(x, y, from, to) \ + mdraw_text_with_control \ + (frame, (MDrawWindow) win, \ + control.orientation_reversed ? x + win_width : x, y, \ + mt, from, to, &control) + +/* Store the extents of a text in the range $FROM to $TO in the + structure $RECT (type MDrawMetric). */ +#define TEXT_EXTENTS(from, to, rect) \ + mdraw_text_extents (frame, mt, from, (to), &control, NULL, NULL, &(rect)) + +/* Store the glyph information of a character at the position $POS in + the struct $INFO (type MDrawGlyphInfo) assuming that the text from + $FROM is written at the coordinate (0, 0). */ +#define GLYPH_INFO(from, pos, info) \ + mdraw_glyph_info (frame, mt, from, (pos), &control, &(info)) + +/* Set $X and $Y to the coordinate of character at position $POS + assuming that the text from $FROM is written at the coordinate (0, + 0). */ +#define COORDINATES_POSITION(from, pos, x, y) \ + mdraw_coordinates_position (frame, mt, (from), (pos), (x), (y), &control) + +/* Interface macros for X library. */ +#define COPY_AREA(y0, y1, to) \ + XCopyArea (display, win, win, gc, 0, (y0), win_width, (y1) - (y0), 0, (to)) + +#define CLEAR_AREA(x, y, w, h) \ + XClearArea (display, win, (x), (y), (w), (h), False) + +#define SELECTEDP() \ + mtext_property_mtext (selection) + +/* Format MSG by FMT and print the result to the stderr, and exit. */ +#define FATAL_ERROR(fmt, arg) \ + do { \ + fprintf (stderr, fmt, arg); \ + exit (1); \ + } while (0) + + +/* If POS is greater than zero, move POS back to the beginning of line + (BOL) position. If FORWARD is nonzero, move POS forward instead. + Return the new position. */ +int +bol (int pos, int forward) +{ + int limit = forward ? nchars : 0; + + pos = mtext_character (mt, pos, limit, '\n'); + return (pos < 0 ? limit : pos + 1); +} + +/* Update the structure #TOP (struct LineInfo) to make $POS the first + character position of the screen. */ +void +update_top (int pos) +{ + int from = bol (pos, 0); + MDrawGlyphInfo info; + + GLYPH_INFO (from, pos, info); + top.from = info.line_from; + top.to = info.line_to; + top.y0 = 0; + top.y1 = info.metrics.height; + top.ascent = - info.metrics.y; +} + + +/* Update the scroll bar so that the text of the range $FROM to $TO + are shown on the window. */ +void +update_scroll_bar (int from, int to) +{ + float top = (float) from / nchars; + float shown = (float) (to - from) / nchars; + + XawScrollbarSetThumb (SbarWidget, top, shown); +} + + +/* Redraw the window area between $Y0 and $Y1 (both Y-codinates). If + $CLEAR is nonzero, clear the area before drawing. If $SCROLL_BAR + is nonzero, update the scoll bar. */ +void +redraw (int y0, int y1, int clear, int scroll_bar) +{ + int from, to; + int y; + MDrawGlyphInfo info; + int sel_y0 = SELECTEDP () ? sel_start.y0 : 0; + struct LineInfo *line; + + if (clear || control.anti_alias) + CLEAR_AREA (0, y0, win_width, y1 - y0); + + /* Find a line closest to y0. It is a cursor line if the cursor is + Y0, otherwise the top line. */ + if (y0 >= cur.y0) + line = &cur; + else + line = ⊤ + /* If there exists a selected region, check it too. */ + if (sel_y0 > line->y0 && y0 >= sel_y0) + line = &sel_start; + + from = line->from; + y = line->y0; + info.metrics.height = line->y1 - y; + info.metrics.y = - line->ascent; + info.line_to = line->to; + while (y + info.metrics.height <= y0) + { + y += info.metrics.height; + from = info.line_to; + if (from >= nchars) + break; + GLYPH_INFO (from, from, info); + } + if (y + info.metrics.height <= y0) + return; + + y0 = y - info.metrics.y; + to = from; + while (to < nchars && y < y1) + { + GLYPH_INFO (to, to, info); + y += info.metrics.height; + to = info.line_to; + } + if (to == nchars) + to++; + if (from < to) + DRAW_TEXT (0, y0, from, to); + if (scroll_bar) + { + while (to < nchars) + { + GLYPH_INFO (to, to, info); + if (y + info.metrics.height >= win_height) + break; + to = info.line_to; + y += info.metrics.height; + } + update_scroll_bar (top.from, to); + } +} + + +/* Set the current input method spot to the correct position. */ +void +set_input_method_spot () +{ + int x = cursor.x + (control.orientation_reversed ? win_width : 0); + int pos = cursor.from > 0 ? cursor.from - 1 : 0; + MFace *faces[256]; + int n = 0; + int size = 0, ratio = 0, i; + + if (nchars > 0) + n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256); + if (n > 0) + for (i = n - 1; i >= 0; i--) + { + if (! size) + size = (int) mface_get_prop (faces[i], Msize); + if (! ratio) + ratio = (int) mface_get_prop (faces[i], Mratio); + } + if (! size) + size = default_font_size; + if (ratio) + size = size * ratio / 100; + minput_set_spot (current_input_context, x, cur.y0 + cur.ascent, + cur.ascent, cur.y1 - (cur.y0 + cur.ascent), size, + mt, cursor.from); +} + + +/* Redraw the cursor. If $CLEAR is nonzero, clear the cursor area + before drawing. */ +void +redraw_cursor (int clear) +{ + if (control.cursor_bidi) + { + /* We must update the whole line of the cursor. */ + int beg = bol (cur.from, 0); + int end = bol (cur.to - 1, 1); + MDrawMetric rect; + int y0 = cur.y0, y1 = cur.y1; + + if (beg < cur.from) + { + TEXT_EXTENTS (beg, cur.from, rect); + y0 -= rect.height; + } + if (end > cur.to) + { + TEXT_EXTENTS (cur.to, end, rect); + y1 += rect.height; + } + redraw (y0, y1, clear, 0); + } + else + { + if (clear) + { + int x = cursor.x; + + if (control.orientation_reversed) + x += win_width - cursor.logical_width; + CLEAR_AREA (x, cur.y0, cursor.logical_width, cursor.metrics.height); + } + DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to); + } +} + + +/* Update the information about the location of cursor to the position + $POS. If $FULL is nonzero, update the information fully only from + the information about the top line. Otherwise, trust the current + information in the structure $CUR. */ +void +update_cursor (int pos, int full) +{ + MDrawMetric rect; + + control.cursor_pos = pos; + if (full) + { + /* CUR is inaccurate. We can trust only TOP. */ + GLYPH_INFO (top.from, pos, cursor); + cur.y0 = top.ascent + cursor.y + cursor.metrics.y; + } + else if (pos < cur.from) + { + int from = bol (pos, 0); + + TEXT_EXTENTS (from, cur.from, rect); + GLYPH_INFO (from, pos, cursor); + cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.metrics.y); + } + else if (pos < cur.to) + { + GLYPH_INFO (cur.from, pos, cursor); + } + else + { + GLYPH_INFO (cur.from, pos, cursor); + cur.y0 += cur.ascent + cursor.y + cursor.metrics.y; + } + + cur.from = cursor.line_from; + cur.to = cursor.line_to; + cur.y1 = cur.y0 + cursor.metrics.height; + cur.ascent = - cursor.metrics.y; +} + + +/* Update the information about the selected region. */ +void +update_selection () +{ + int from, to; + MDrawMetric rect; + MDrawGlyphInfo info; + + if (! SELECTEDP ()) + return; + from = mtext_property_start (selection); + to = mtext_property_end (selection); + + if (from < top.from) + { + int pos = bol (from, 0); + + TEXT_EXTENTS (pos, top.from, rect); + sel_start.y0 = top.y0 - rect.height; + sel_start.ascent = - rect.y; + GLYPH_INFO (pos, from, info); + if (pos < info.line_from) + sel_start.y0 += - rect.y + info.y + info.metrics.y; + } + else + { + GLYPH_INFO (top.from, from, info); + sel_start.y0 = top.ascent + info.y + info.metrics.y; + } + sel_start.ascent = -info.metrics.y; + sel_start.y1 = sel_start.y0 + info.metrics.height; + sel_start.from = info.line_from; + sel_start.to = info.line_to; + + if (to <= sel_start.to) + { + sel_end = sel_start; + } + else + { + GLYPH_INFO (sel_start.from, to, info); + sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.metrics.y; + sel_end.y1 = sel_end.y0 + info.metrics.height; + sel_end.ascent = - info.metrics.y; + sel_end.from = info.line_from; + sel_end.to = info.line_to; + } +} + + +/* Select the text in the region from $FROM to $TO. */ +void +select_region (int from, int to) +{ + int pos; + + if (from > to) + pos = from, from = to, to = pos; + mtext_push_property (mt, from, to, selection); + update_selection (); +} + + +/* Setup the window to display the character of $POS at the top left + of the window. */ +void +reseat (int pos) +{ + MDrawMetric rect; + /* Top and bottom Y positions to redraw. */ + int y0, y1; + + if (pos + 1000 < top.from) + y0 = 0, y1 = win_height; + else if (pos < top.from) + { + y0 = 0; + TEXT_EXTENTS (pos, top.from, rect); + if (rect.height >= win_height * 0.9) + y1 = win_height; + else + { + y1 = rect.height; + COPY_AREA (0, win_height - y1, y1); + } + } + else if (pos < top.to) + { + /* No need of redrawing. */ + y0 = y1 = 0; + } + else if (pos < top.from + 1000) + { + TEXT_EXTENTS (top.from, pos, rect); + if (rect.height >= win_height * 0.9) + y0 = 0; + else + { + y0 = win_height - rect.height; + COPY_AREA (rect.height, win_height, 0); + } + y1 = win_height; + } + else + y0 = 0, y1 = win_height; + + if (y0 < y1) + { + update_top (pos); + if (cur.to <= pos) + update_cursor (pos, 1); + else + update_cursor (cursor.from, 1); + update_selection (); + redraw (y0, y1, 1, 1); + } +} + +static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *); + + +/* Select an input method accoding to $IDX. If $IDX is negative, turn + off the current input method, otherwide turn on the input method + input_method_table[$IDX]. */ +void +select_input_method (idx) +{ + int previous_input_method = current_input_method; + + if (idx == current_input_method) + return; + if (current_input_method >= 0) + { + minput_destroy_ic (current_input_context); + current_input_context = NULL; + current_input_method = -1; + } + + if (idx >= 0 + && input_method_table[idx].available >= 0) + { + InputMethodInfo *im = input_method_table + idx; + + if (im->available == 0) + { + if (im->language) + im->im = minput_open_im (im->language, im->name, NULL); + else + { + MInputXIMArgIM arg_xim; + + arg_xim.display = display; + arg_xim.db = NULL; + arg_xim.res_name = arg_xim.res_class = NULL; + arg_xim.locale = NULL; + arg_xim.modifier_list = NULL; + im->im = minput_open_im (Mnil, im->name, &arg_xim); + } + im->available = im->im ? 1 : -1; + } + if (im->im) + { + if (im->language == Mnil) + { + MInputXIMArgIC arg_xic; + Window win = XtWindow (TextWidget); + + arg_xic.input_style = 0; + arg_xic.client_win = arg_xic.focus_win = win; + arg_xic.preedit_attrs = arg_xic.status_attrs = NULL; + current_input_context = minput_create_ic (im->im, &arg_xic); + } + else + { + MInputGUIArgIC arg_ic; + + arg_ic.frame = frame; + arg_ic.client = (MDrawWindow) XtWindow (ShellWidget); + arg_ic.focus = (MDrawWindow) XtWindow (TextWidget); + current_input_context = minput_create_ic (im->im, &arg_ic); + } + + if (current_input_context) + { + current_input_method = idx; + set_input_method_spot (); + } + else + { + minput_close_im (im->im); + im->im = NULL; + im->available = -1; + current_input_method = -1; + } + } + } + if (! auto_input_method) + { + XtSetArg (arg[0], XtNleftBitmap, None); + if (previous_input_method >= 0) + XtSetValues (InputMethodMenus[previous_input_method + 2], arg, 1); + else + XtSetValues (InputMethodMenus[0], arg, 1); + XtSetArg (arg[0], XtNleftBitmap, CheckPixmap); + if (current_input_method >= 0) + XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1); + else + XtSetValues (InputMethodMenus[0], arg, 1); + } + + if (current_input_method >= 0) + { + char *label; + + XtSetArg (arg[0], XtNlabel, &label); + XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1); + XtSetArg (arg[0], XtNlabel, label); + } + else + { + XtSetArg (arg[0], XtNlabel, ""); + } + XtSetValues (CurIMLang, arg, 1); +} + +static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num); + + +/* Display cursor according to the current information of #CUR. + $CLIENT_DATA is ignore. Most callback functions add this function + as a background processing procedure the current application (by + XtAppAddWorkProc) via the function hide_cursor. */ +Boolean +show_cursor (XtPointer client_data) +{ + MFaceHLineProp *hline; + MFaceBoxProp *box; + + if (cur.y0 < 0) + { + reseat (cur.from); + update_cursor (cursor.from, 1); + } + while (cur.y1 > win_height) + { + reseat (top.to); + update_cursor (cursor.from, 1); + } + + control.cursor_pos = cursor.from; + if (! SELECTEDP ()) + { + control.with_cursor = 1; + redraw_cursor (0); + } + if (current_input_context) + set_input_method_spot (); + + if (nchars > 0) + { + int pos = (SELECTEDP () ? mtext_property_start (selection) + : cursor.from > 0 ? cursor.from - 1 + : cursor.from); + MFace *face = mface (); + MTextProperty *props[256]; + int n = mtext_get_properties (mt, pos, Mface, props, 256); + int i; + char buf[256], *p = buf; + MSymbol sym; + + buf[0] = '\0'; + if (cursor.font) + { + int size = (int) mfont_get_prop (cursor.font, Msize); + MSymbol family = mfont_get_prop (cursor.font, Mfamily); + MSymbol weight = mfont_get_prop (cursor.font, Mweight); + MSymbol style = mfont_get_prop (cursor.font, Mstyle); + MSymbol registry = mfont_get_prop (cursor.font, Mregistry); + + sprintf (p, "%dpt", size / 10), p += strlen (p); + if (family) + strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p); + if (weight) + strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p); + if (style) + strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p); + if (registry) + strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p); + p += strlen (p); + } + + mface_merge (face, face_default); + for (i = 0; i < n; i++) + if (props[i] != selection) + mface_merge (face, (MFace *) mtext_property_value (props[i])); + sym = (MSymbol) mface_get_prop (face, Mforeground); + if (sym != Mnil) + strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p); + if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse) + strcat (p, ",rev"), p += strlen (p); + hline = mface_get_prop (face, Mhline); + if (hline && hline->width > 0) + strcat (p, ",ul"), p += strlen (p); + box = mface_get_prop (face, Mbox); + if (box && box->width > 0) + strcat (p, ",box"), p += strlen (p); + m17n_object_unref (face); + + XtSetArg (arg[0], XtNborderWidth, 1); + XtSetArg (arg[1], XtNlabel, buf); + XtSetValues (CurFaceWidget, arg, 2); + } + + if (control.cursor_pos < nchars) + { + MSymbol sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage); + + if (sym == Mnil) + { + XtSetArg (arg[0], XtNborderWidth, 0); + XtSetArg (arg[1], XtNlabel, ""); + } + else + { + XtSetArg (arg[0], XtNborderWidth, 1); + sym = mlanguage_name (sym); + XtSetArg (arg[1], XtNlabel, msymbol_name (sym)); + XtSetValues (CurLangWidget, arg, 2); + } + XtSetValues (CurLangWidget, arg, 2); + + if (auto_input_method) + { + if (sym == Mnil) + select_input_method (-1); + else + { + int i; + + for (i = 0; i < num_input_methods; i++) + if (input_method_table[i].language == sym + && input_method_table[i].available >= 0) + break; + if (i < num_input_methods) + select_input_method (i); + else + select_input_method (-1); + } + } + } + + MenuHelpProc (MessageWidget, NULL, NULL, NULL); + + return True; +} + + +/* Hide the cursor. */ +void +hide_cursor () +{ + control.with_cursor = 0; + redraw_cursor (1); + XtAppAddWorkProc (context, show_cursor, NULL); +} + + +/* Update the window area between the Y-positions $Y0 and $OLD_Y1 to + $Y1 and $NEW_Y1 assuming that the text in the other area is not + changed. */ +void +update_region (int y0, int old_y1, int new_y1) +{ + if (y0 < 0) + y0 = 0; + if (new_y1 < old_y1) + { + if (old_y1 < win_height) + { + COPY_AREA (old_y1, win_height, new_y1); + redraw (win_height - (old_y1 - new_y1), win_height, 1, 0); + } + else + redraw (new_y1, win_height, 1, 0); + } + else if (new_y1 > old_y1) + { + if (new_y1 < win_height) + COPY_AREA (old_y1, win_height, new_y1); + } + if (new_y1 > win_height) + new_y1 = win_height; + redraw (y0, new_y1, 1, 1); +} + + +/* Delete the next $N characters. If $N is negative delete the + precious (- $N) characters. */ +void +delete_char (int n) +{ + MDrawMetric rect; + MDrawGlyphInfo info; + int y0, old_y1, new_y1; + int from, to; + int line_from = cursor.line_from; + + if (n > 0) + from = cursor.from, to = from + n; + else + { + from = cursor.from + n; + to = cursor.from; + if (cursor.from == cur.from) + { + /* We are at the beginning of line. */ + int pos = cursor.prev_from; + + if (cursor.from == top.from) + { + /* We are at the beginning of screen. We must scroll + down. */ + GLYPH_INFO (bol (top.from - 1, 0), top.from - 1, info); + reseat (info.line_from); + } + update_cursor (pos, 1); + } + } + + TEXT_EXTENTS (cur.from, bol (to + 1, 1), rect); + old_y1 = cur.y0 + rect.height; + + /* Now delete a character. */ + mtext_del (mt, from, to); + nchars -= to - from; + if (from >= top.from && from < top.to) + update_top (top.from); + update_cursor (from, 1); + + y0 = cur.y0; + if (line_from != cursor.line_from) + y0 -= 1; + + TEXT_EXTENTS (cur.from, bol (to, 1), rect); + new_y1 = cur.y0 + rect.height; + + update_region (cur.y0, old_y1, new_y1); +} + + +/* Insert M-text $NEWTEXT at the current cursor position. */ +void +insert_chars (MText *newtext) +{ + int n = mtext_len (newtext); + MDrawMetric rect; + int y0, old_y1, new_y1; + int line_from; + + if (SELECTEDP ()) + { + int n = (mtext_property_end (selection) + - mtext_property_start (selection)); + mtext_detach_property (selection); + delete_char (n); + } + + y0 = cur.y0; + if (cursor.line_from > 0 + && mtext_ref_char (mt, cursor.line_from - 1) != '\n') + y0 -= control.min_line_descent; + + TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect); + old_y1 = y0 + rect.height; + + line_from = cursor.line_from; + + /* Now insert chars. */ + mtext_ins (mt, cursor.from, newtext); + nchars += n; + if (cur.from == top.from) + update_top (top.from); + update_cursor (cursor.from + n, 1); + + TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect); + new_y1 = cur.y0 + rect.height; + + update_region (y0, old_y1, new_y1); + update_selection (); +} + + +int +word_constituent_p (int c) +{ + MSymbol category = (MSymbol) mchar_get_prop (c, Mcategory); + char *name = category != Mnil ? msymbol_name (category) : NULL; + + return (name && (name[0] == 'L' || name[0] == 'M')); +} + + +void +forward_word () +{ + int pos = cursor.from; + + while (pos < nchars && ! word_constituent_p (mtext_ref_char (mt, pos))) + pos++; + if (pos < nchars) + { + MTextProperty *prop = mtext_get_property (mt, pos, Mword); + + if (prop) + pos = mtext_property_end (prop); + else + while (pos < nchars && word_constituent_p (mtext_ref_char (mt, pos))) + pos++; + } + update_cursor (pos, 0); +} + +void +backward_word () +{ + int pos = cursor.from; + + while (pos > 0 && ! word_constituent_p (mtext_ref_char (mt, pos - 1))) + pos--; + if (pos > 0) + { + MTextProperty *prop = mtext_get_property (mt, pos - 1, Mword); + + if (prop) + pos = mtext_property_start (prop); + else + while (pos > 0 && word_constituent_p (mtext_ref_char (mt, pos - 1))) + pos--; + } + update_cursor (pos, 0); +} + + +/* Convert the currently selected text to UTF8-STRING or + COMPOUND-TEXT. It is called when someone requests the current + value of the selection. */ +Boolean +covert_selection (Widget w, Atom *selection_atom, + Atom *target, Atom *return_type, + XtPointer *value, unsigned long *length, int *format) +{ + unsigned char *buf = (unsigned char *) XtMalloc (4096); + MText *this_mt = mtext (); + int from = mtext_property_start (selection); + int to = mtext_property_end (selection); + MSymbol coding; + int len; + + mtext_copy (this_mt, 0, mt, from, to); + if (*target == XA_TEXT) + { +#ifdef X_HAVE_UTF8_STRING + coding = Mcoding_utf_8; + *return_type = XA_UTF8_STRING; +#else + coding = Mcoding_compound_text; + *return_type = XA_COMPOUND_TEXT; +#endif + } + else if (*target == XA_UTF8_STRING) + { + coding = Mcoding_utf_8; + *return_type = XA_UTF8_STRING; + } + else if (*target == XA_STRING) + { + int i; + + len = to - from; + for (i = 0; i < len; i++) + if (mtext_ref_char (this_mt, i) >= 0x100) + /* Can't encode in XA_STRING */ + return False; + coding = Mcoding_iso_8859_1; + *return_type = XA_STRING; + } + else if (*target == XA_COMPOUND_TEXT) + { + coding = Mcoding_compound_text; + *return_type = XA_COMPOUND_TEXT; + } + else + return False; + + len = mconv_encode_buffer (coding, this_mt, buf, 4096); + m17n_object_unref (this_mt); + if (len < 0) + return False; + *length = len; + *value = (XtPointer) buf; + *format = 8; + return True; +} + + +/* Unselect the text. It is called when we loose the selection. */ +void +lose_selection (Widget w, Atom *selection_atom) +{ + if (SELECTEDP ()) + { + mtext_detach_property (selection); + redraw (sel_start.y0, sel_end.y1, 1, 0); + } +} + +void +get_selection (Widget w, XtPointer cliend_data, Atom *selection, Atom *type, + XtPointer value, unsigned long *length, int *format) +{ + MText *this_mt; + MSymbol coding; + + if (*type == XT_CONVERT_FAIL || ! value) + goto err; + if (*type == XA_STRING) + coding = Mnil; + else if (*type == XA_COMPOUND_TEXT) + coding = msymbol ("compound-text"); +#ifdef X_HAVE_UTF8_STRING + else if (*type == XA_UTF8_STRING) + coding = msymbol ("utf-8"); +#endif + else + goto err; + + this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length); + if (! this_mt && *type != XA_UTF8_STRING) + { + XtGetSelectionValue (w, XA_PRIMARY, XA_UTF8_STRING, get_selection, NULL, + CurrentTime); + goto err; + } + if (this_mt) + { + hide_cursor (); + insert_chars (this_mt); + m17n_object_unref (this_mt); + } + + err: + if (value) + XtFree (value); +} + +static void +ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num) +{ + XExposeEvent *expose = (XExposeEvent *) event; + + if (top.from < 0) + { + Dimension width_max, width; + + XtSetArg (arg[0], XtNwidth, &width); + XtGetValues (XtParent (w), arg, 1); + width_max = width; + XtGetValues (HeadWidget, arg, 1); + if (width_max < width) + width_max = width; + XtGetValues (FaceWidget, arg, 1); + if (width_max < width) + width_max = width; + XtGetValues (LangWidget, arg, 1); + if (width_max < width) + width_max = width; + XtSetArg (arg[0], XtNwidth, width_max); + XtSetValues (HeadWidget, arg, 1); + XtSetValues (FaceWidget, arg, 1); + XtSetValues (LangWidget, arg, 1); + XtSetValues (XtParent (w), arg, 1); + XtSetValues (TailWidget, arg, 1); + + update_top (0); + update_cursor (0, 1); + redraw (0, win_height, 0, 1); + if (current_input_method >= 0) + { + int idx = current_input_method; + + current_input_method = -1; + select_input_method (idx); + } + show_cursor (NULL); + } + else + { + redraw (expose->y, expose->y + expose->height, 0, 0); + if (current_input_context + && expose->y < cur.y0 && expose->y + expose->height < cur.y1) + set_input_method_spot (); + } +} + +static void +ConfigureProc (Widget w, XEvent *event, String *str, Cardinal *num) +{ + XConfigureEvent *configure = (XConfigureEvent *) event; + + hide_cursor (); + control.max_line_width = win_width = configure->width; + win_height = configure->height; + mdraw_clear_cache (mt); + update_top (0); + update_cursor (0, 1); + redraw (0, win_height, 1, 1); + if (current_input_context) + set_input_method_spot (); +} + +static void +ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num) +{ + int pos; + int x = event->xbutton.x; + int y = event->xbutton.y - top.ascent; + + if (control.orientation_reversed) + x -= win_width; + pos = COORDINATES_POSITION (top.from, nchars + 1, x, y); + if (SELECTEDP ()) + { + XtDisownSelection (w, XA_PRIMARY, CurrentTime); + mtext_detach_property (selection); + redraw (sel_start.y0, sel_end.y1, 1, 0); + } + hide_cursor (); + if (current_input_context + && minput_filter (current_input_context, Minput_focus_move, NULL) == 0) + { + MText *produced = mtext (); + + minput_lookup (current_input_context, Mnil, NULL, produced); + if (mtext_len (produced) > 0) + { + insert_chars (produced); + if (pos >= cursor.from) + pos += mtext_len (produced); + } + m17n_object_unref (produced); + } + update_cursor (pos, 0); +} + + +static void +ButtonReleaseProc (Widget w, XEvent *event, String *str, Cardinal *num) +{ + if (! SELECTEDP ()) + return; + + XtOwnSelection (w, XA_PRIMARY, CurrentTime, + covert_selection, lose_selection, NULL); + update_cursor (mtext_property_start (selection), 0); +} + +static +void +Button2Proc (Widget w, XEvent *event, String *str, Cardinal *num) +{ + if (! SELECTEDP ()) + { + /* We don't have a local selection. */ + XtGetSelectionValue (w, XA_PRIMARY, XA_TEXT, get_selection, NULL, + CurrentTime); + } + else + { + int from = mtext_property_start (selection); + int to = mtext_property_end (selection); + MText *this_mt; + int pos; + int x = event->xbutton.x; + int y = event->xbutton.y - top.ascent; + + if (control.orientation_reversed) + x -= win_width; + pos = COORDINATES_POSITION (top.from, nchars + 1, x, y); + + XtDisownSelection (w, XA_PRIMARY, CurrentTime); + mtext_detach_property (selection); + hide_cursor (); + this_mt = mtext_copy (mtext (), 0, mt, from, to); + update_cursor (pos, 0); + insert_chars (this_mt); + m17n_object_unref (this_mt); + } +} + +static void +ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num) +{ + int pos; + int x = event->xbutton.x; + int y = event->xbutton.y; + + if (control.orientation_reversed) + x -= win_width; + if (y < cur.y0) + pos = top.from, y -= top.ascent; + else + pos = cur.from, y -= cur.y0 + cur.ascent; + pos = COORDINATES_POSITION (pos, nchars + 1, x, y); + + if (pos == cursor.from) + return; + + hide_cursor (); + if (SELECTEDP ()) + { + /* Selection range changed. */ + int from = mtext_property_start (selection); + int to = mtext_property_end (selection); + int start_y0 = sel_start.y0, start_y1 = sel_start.y1; + int end_y0 = sel_end.y0, end_y1 = sel_end.y1; + + if (cursor.from == from) + { + /* Starting position changed. */ + if (pos <= from) + { + /* Enlarged. We can simply overdraw. */ + select_region (pos, to); + redraw (sel_start.y0, start_y1, 0, 0); + } + else if (pos < to) + { + /* Shrunken. Previous selection face must be cleared. */ + select_region (pos, to); + redraw (start_y0, sel_start.y1, 1, 0); + } + else if (pos == to) + { + /* Shrunken to zero. */ + XtDisownSelection (w, XA_PRIMARY, CurrentTime); + mtext_detach_property (selection); + redraw (start_y0, end_y1, 1, 0); + } + else + { + /* Full update is necessary. */ + select_region (to, pos); + redraw (start_y0, sel_end.y1, 1, 0); + } + } + else + { + /* Ending position changed. */ + if (pos < from) + { + /* Full update is necessary. */ + select_region (pos, from); + redraw (sel_start.y0, end_y1, 1, 0); + } + else if (pos == from) + { + /* Shrunken to zero. */ + XtDisownSelection (w, XA_PRIMARY, CurrentTime); + mtext_detach_property (selection); + redraw (start_y0, end_y1, 1, 0); + } + else if (pos < to) + { + /* Shrunken. Previous selection face must be cleared. */ + select_region (from, pos); + redraw (sel_end.y0, end_y1, 1, 0); + } + else + { + /* Enlarged. We can simply overdraw. */ + select_region (from, pos); + redraw (end_y0, sel_end.y1, 0, 0); + } + } + } + else + { + /* Newly selected. */ + select_region (pos, cursor.from); + redraw (sel_start.y0, sel_end.y1, 0, 0); + } + update_cursor (pos, 1); +} + +void +FocusInProc (Widget w, XEvent *event, String *str, Cardinal *num) +{ + if (current_input_context + && minput_filter (current_input_context, Minput_focus_in, NULL) == 0) + { + MText *produced = mtext (); + + minput_lookup (current_input_context, Mnil, NULL, produced); + if (mtext_len (produced) > 0) + { + hide_cursor (); + insert_chars (produced); + } + m17n_object_unref (produced); + } +} + +void +FocusOutProc (Widget w, XEvent *event, String *str, Cardinal *num) +{ + if (current_input_context + && minput_filter (current_input_context, Minput_focus_out, NULL) == 0) + { + MText *produced = mtext (); + + minput_lookup (current_input_context, Mnil, NULL, produced); + if (mtext_len (produced) > 0) + { + hide_cursor (); + insert_chars (produced); + } + m17n_object_unref (produced); + } +} + +void +ScrollProc (Widget w, XtPointer client_data, XtPointer position) +{ + int from; + MDrawGlyphInfo info; + int height; + int cursor_pos = cursor.from; + + if (((int) position) < 0) + { + /* Scroll down. */ + int pos; + + from = top.from; + height = top.y1 - top.y0; + while (from > 0) + { + pos = bol (from - 1, 0); + GLYPH_INFO (pos, from - 1, info); + if (height + info.metrics.height > win_height) + break; + height += info.metrics.height; + from = info.line_from; + } + if (cursor_pos >= top.to) + { + cursor_pos = top.from; + pos = top.to; + while (cursor_pos < nchars) + { + GLYPH_INFO (pos, pos, info); + if (height + info.metrics.height > win_height) + break; + height += info.metrics.height; + cursor_pos = pos; + pos = info.line_to; + } + } + } + else if (cur.to < nchars) + { + /* Scroll up, but leave at least one line. */ + from = cur.to; + height = cur.y1; + while (from < nchars) + { + GLYPH_INFO (from, from, info); + if (height + info.metrics.height > win_height + || info.line_to >= nchars) + break; + height += info.metrics.height; + from = info.line_to; + } + if (from == nchars) + from = info.line_from; + if (cursor_pos < from) + cursor_pos = from; + } + else + /* Scroll up to make the cursor line top. */ + from = cur.from; + hide_cursor (); + reseat (from); + update_cursor (cursor_pos, 1); +} + +void +JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr) +{ + float persent = *(float *) persent_ptr; + int pos1, pos2 = nchars * persent; + MDrawGlyphInfo info; + + hide_cursor (); + pos1 = bol (pos2, 0); + GLYPH_INFO (pos1, pos2, info); + pos1 = info.line_from; + reseat (pos1); + update_cursor (pos1, 1); +} + +static void InputMethodProc (Widget, XtPointer, XtPointer); + +static void +KeyProc (Widget w, XEvent *event, String *str, Cardinal *num) +{ + XKeyEvent *key_event = (XKeyEvent *) event; + char buf[512]; + KeySym keysym = NoSymbol; + int ret; + /* If set to 1, do not update target_x_position. */ + int keep_target_x_position = 0; + MText *produced; + int y0, old_y1, new_y1; + + hide_cursor (); + + mt_modified = 0; + y0 = cur.y0; + old_y1 = cur.y1; + if (current_input_context + && minput_filter (current_input_context, Mnil, event)) + { + if (mt_modified) + { + new_y1 = cur.y1; + update_region (y0, old_y1, new_y1); + } + return; + } + if (event->type == KeyRelease) + return; + + produced = mtext (); + ret = minput_lookup (current_input_context, Mnil, event, produced); + if (mtext_len (produced) > 0) + insert_chars (produced); + if (ret) + ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL); + m17n_object_unref (produced); + + if (saved_input_method > -3) + { + InputMethodProc (w, (XtPointer) saved_input_method, NULL); + saved_input_method = -3; + } + + switch (keysym) + { + case XK_Delete: + { + int n = 0; + + if (SELECTEDP ()) + { + n = (mtext_property_end (selection) + - mtext_property_start (selection)); + mtext_detach_property (selection); + } + else if (cursor.from < nchars) + { + /* Delete the following grapheme cluster. */ + n = cursor.to - cursor.from; + } + if (n != 0) + delete_char (n); + } + break; + + case XK_BackSpace: + { + int n = 0; + + if (SELECTEDP ()) + { + /* Delete selected region. */ + n = (mtext_property_end (selection) + - mtext_property_start (selection)); + mtext_detach_property (selection); + } + else if (cursor.from > 0) + { + /* Delete the preceding character. */ + n = -1; + } + if (n != 0) + delete_char (n); + } + break; + + case XK_Left: + if (SELECTEDP ()) + { + mtext_detach_property (selection); + redraw (sel_start.y0, sel_end.y1, 1, 0);; + } + if (logical_move) + { + if (cursor.prev_from >= 0) + update_cursor (cursor.prev_from, 0); + } + else + { + if (cursor.left_from >= 0) + update_cursor (cursor.left_from, 0); + } + break; + + case XK_Right: + if (SELECTEDP ()) + { + mtext_detach_property (selection); + redraw (sel_start.y0, sel_end.y1, 1, 0);; + } + if (logical_move) + { + if (cursor.next_to >= 0) + update_cursor (cursor.to, 0); + } + else + { + if (cursor.right_from >= 0) + update_cursor (cursor.right_from, 0); + } + break; + + case XK_Down: + if (SELECTEDP ()) + { + mtext_detach_property (selection); + redraw (sel_start.y0, sel_end.y1, 1, 0);; + } + if (cur.to <= nchars) + { + MDrawGlyphInfo info; + int pos; + + GLYPH_INFO (cur.from, cur.to, info); + pos = COORDINATES_POSITION (cur.from, nchars + 1, + target_x_position, info.y); + keep_target_x_position = 1; + update_cursor (pos, 0); + } + break; + + case XK_Up: + if (SELECTEDP ()) + { + mtext_detach_property (selection); + redraw (sel_start.y0, sel_end.y1, 1, 0);; + } + if (cur.from > 0) + { + MDrawMetric rect; + int y; + int pos = bol (cur.from - 1, 0); + + TEXT_EXTENTS (pos, cur.from - 1, rect); + y = rect.height + rect.y - 1; + pos = COORDINATES_POSITION (pos, nchars, + target_x_position, y); + keep_target_x_position = 1; + update_cursor (pos, 0); + } + break; + + case XK_Page_Down: + if (SELECTEDP ()) + { + mtext_detach_property (selection); + redraw (sel_start.y0, sel_end.y1, 1, 0);; + } + if (top.from < nchars) + ScrollProc (w, NULL, (XtPointer) 1); + break; + + case XK_Page_Up: + if (SELECTEDP ()) + { + mtext_detach_property (selection); + redraw (sel_start.y0, sel_end.y1, 1, 0);; + } + if (top.from > 0) + ScrollProc (w, NULL, (XtPointer) -1); + break; + + case XK_b: + if (key_event->state >= Mod1Mask) + { + lose_selection (NULL, NULL); + backward_word (); + break; + } + + case XK_f: + if (key_event->state >= Mod1Mask) + { + lose_selection (NULL, NULL); + forward_word (); + break; + } + + default: + if (ret > 0) + { + if (buf[0] == 17) /* C-q */ + { + XtAppSetExitFlag (context); + return; + } + else if (buf[0] == 12) /* C-l */ + { + redraw (0, win_height, 1, 1); + return; + } + else if (buf[0] == '=' + && (event->xkey.state & ControlMask) + && unicode_input_method >= 0) + { + saved_input_method = current_input_method; + InputMethodProc (w, (XtPointer) unicode_input_method, NULL); + minput_filter (current_input_context, msymbol ("C-u"), NULL); + } + else + { + MText *temp = mtext (); + + mtext_cat_char (temp, buf[0] == '\r' ? '\n' + : ((unsigned char *) buf)[0]); + if (current_input_context) + mtext_put_prop (temp, 0, 1, Mlanguage, + current_input_context->im->language); + insert_chars (temp); + m17n_object_unref (temp); + } + } + } + + if (! keep_target_x_position) + target_x_position = cursor.x; +} + +void +SaveProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + char *name = (char *) client_data; + FILE *fp; + int from = -1, to = 0; + + if (name) + { + free (filename); + filename = strdup (name); + } + + fp = fopen (filename, "w"); + if (! fp) + { + fprintf (stderr, "Open for write fail: %s", filename); + return; + } + + if (SELECTEDP ()) + { + from = mtext_property_start (selection); + to = mtext_property_end (selection); + mtext_detach_property (selection); + } + + mconv_encode_stream (Mcoding_utf_8_full, mt, fp); + fclose (fp); + if (from >= 0) + select_region (from, to); +} + +void +SerializeProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + MText *new; + + hide_cursor (); + if (SELECTEDP ()) + mtext_detach_property (selection); + serialized = (int) client_data; + if (! serialized) + new = mtext_deserialize (mt); + else + { + MPlist *plist = mplist (); + + mplist_push (plist, Mt, Mface); + mplist_push (plist, Mt, Mlanguage); + new = mtext_serialize (mt, 0, mtext_len (mt), plist); + m17n_object_unref (plist); + } + if (new) + { + m17n_object_unref (mt); + mt = new; + serialized = ! serialized; + nchars = mtext_len (mt); + update_top (0); + } + update_cursor (0, 1); + redraw (0, win_height, 1, 1); +} + +void +QuitProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + XtAppSetExitFlag (context); +} + +MText * +read_file () +{ + FILE *fp = fopen (filename, "r"); + + if (! fp) + FATAL_ERROR ("Can't read \"%s\"!\n", filename); + mt = mconv_decode_stream (Mcoding_utf_8_full, fp); + fclose (fp); + if (! mt) + FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename); + return mt; +} + +void +BidiProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + int data = (int) client_data; + int i; + + if (data == 0) + { + control.enable_bidi = 0; + control.orientation_reversed = 0; + } + else + { + control.enable_bidi = 1; + control.orientation_reversed = data == 2; + } + for (i = 0; i < 3; i++) + { + if (i == data) + XtSetArg (arg[0], XtNleftBitmap, CheckPixmap); + else + XtSetArg (arg[0], XtNleftBitmap, None); + XtSetValues (BidiMenus[i], arg, 1); + } + + update_cursor (cursor.from, 1); + redraw (0, win_height, 1, 0); +} + +void +LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + int data = (int) client_data; + int i; + + if (data == 0) + control.max_line_width = 0; + else + { + control.max_line_width = win_width; + control.line_break = (data == 1 ? NULL : mdraw_default_line_break); + } + for (i = 0; i < 3; i++) + { + if (i == data) + XtSetArg (arg[0], XtNleftBitmap, CheckPixmap); + else + XtSetArg (arg[0], XtNleftBitmap, None); + XtSetValues (LineBreakMenus[i], arg, 1); + } + + update_cursor (cursor.from, 1); + redraw (0, win_height, 1, 0); +} + +void +FilterProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + char *filter_module = (char *) client_data; + void *handle; + void (*func) (MText *, int, int); + + if (! SELECTEDP ()) + return; + handle = dlopen (filter_module, RTLD_NOW); + if (! handle) + return; + func = (void (*) (MText *, int, int)) dlsym (handle, "filter"); + if (func) + (*func) (mt, mtext_property_start (selection), + mtext_property_end (selection)); + dlclose (handle); +} + +void +CursorProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + int data = (int) client_data; + int i, from, to; + + switch (data) + { + case 0: + logical_move = 1; + from = 0, to = 2; + break; + case 1: + logical_move = 0; + from = 0, to = 2; + break; + case 2: + control.cursor_bidi = 0, control.cursor_width = -1; + from = 2, to = 5; + break; + case 3: + control.cursor_bidi = 0, control.cursor_width = 2; + from = 2, to = 5; + break; + default: + control.cursor_bidi = 1; + from = 2, to = 5; + break; + } + + for (i = from; i < to; i++) + { + if (i == data) + XtSetArg (arg[0], XtNleftBitmap, CheckPixmap); + else + XtSetArg (arg[0], XtNleftBitmap, None); + XtSetValues (CursorMenus[i], arg, 1); + } + + update_cursor (cursor.from, 0); + redraw (0, win_height, 1, 0); +} + +static void +InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + int idx = (int) client_data; + + if (idx == -2 ? (! auto_input_method && current_input_method < 0) + : idx == -1 ? auto_input_method + : idx == current_input_method) + return; + + if (auto_input_method) + { + select_input_method (-1); + XtSetArg (arg[0], XtNleftBitmap, None); + XtSetValues (InputMethodMenus[1], arg, 1); + auto_input_method = 0; + } + + if (idx == -1) + { + select_input_method (-1); + XtSetArg (arg[0], XtNleftBitmap, None); + XtSetValues (InputMethodMenus[0], arg, 1); + XtSetArg (arg[0], XtNleftBitmap, CheckPixmap); + XtSetValues (InputMethodMenus[1], arg, 1); + auto_input_method = 1; + hide_cursor (); + } + else + { + select_input_method (idx); + } +} + +MPlist *default_face_list; + +void +FaceProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + int idx = (int) client_data; + int from, to; + int old_y1; + + hide_cursor (); + if (! SELECTEDP ()) + { + MPlist *plist; + + if (idx >= 0) + { + MFace *face = mframe_get_prop (frame, Mface); + + for (plist = default_face_list; mplist_key (plist) != Mnil; + plist = mplist_next (plist)) + mface_merge (face, mplist_value (plist)); + mplist_add (plist, Mt, *face_table[idx].face); + mface_merge (face, *face_table[idx].face); + } + else if (mplist_key (mplist_next (default_face_list)) != Mnil) + { + MFace *face = mframe_get_prop (frame, Mface); + + for (plist = default_face_list; + mplist_key (mplist_next (plist)) != Mnil; + plist = mplist_next (plist)) + mface_merge (face, mplist_value (plist)); + mplist_pop (plist); + } + update_top (0); + update_cursor (0, 1); + redraw (0, win_height, 1, 1); + show_cursor (NULL); + return; + } + + XtAppAddWorkProc (context, show_cursor, NULL); + from = mtext_property_start (selection); + to = mtext_property_end (selection); + old_y1 = sel_end.y1; + + mtext_detach_property (selection); + if (idx >= 0) + { + MTextProperty *prop = mtext_property (Mface, *face_table[idx].face, + MTEXTPROP_REAR_STICKY); + mtext_push_property (mt, from, to, prop); + m17n_object_unref (prop); + } + else + mtext_pop_prop (mt, from, to, Mface); + if (from < top.to) + update_top (top.from); + update_cursor (cursor.from, 1); + select_region (from, to); + update_region (sel_start.y0, old_y1, sel_end.y1); + if (cur.y1 > win_height) + { + while (cur.y1 > win_height) + { + reseat (top.to); + update_cursor (cursor.from, 1); + } + } +} + +void +LangProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + MSymbol sym = (MSymbol) client_data; + int from, to; + int old_y1; + + if (! SELECTEDP ()) + return; + + XtAppAddWorkProc (context, show_cursor, NULL); + from = mtext_property_start (selection); + to = mtext_property_end (selection); + old_y1 = sel_end.y1; + + mtext_detach_property (selection); + if (sym != Mnil) + mtext_put_prop (mt, from, to, Mlanguage, sym); + else + mtext_pop_prop (mt, from, to, Mlanguage); + + if (from < top.to) + update_top (top.from); + update_cursor (cursor.from, 1); + select_region (from, to); + update_region (sel_start.y0, old_y1, sel_end.y1); + if (cur.y1 > win_height) + { + while (cur.y1 > win_height) + { + reseat (top.to); + update_cursor (cursor.from, 1); + } + } +} + +void +DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + int narrowed = (int) client_data; + FILE *mdump; + int from, to; + MConverter *converter; + + if (narrowed) + { + if (! SELECTEDP ()) + return; + from = mtext_property_start (selection); + to = mtext_property_end (selection); + } + else + { + from = 0; + to = nchars; + } + + if (! narrowed) + mdump = popen ("mdump -q -p a4", "w"); + else + mdump = popen ("mdump -q", "w"); + if (! mdump) + return; + converter = mconv_stream_converter (Mcoding_utf_8_full, mdump); + mconv_encode_range (converter, mt, from, to); + mconv_free_converter (converter); + fclose (mdump); +} + +void +input_status (MInputContext *ic, MSymbol command) +{ + XFillRectangle (display, input_status_pixmap, gc_inv, + 0, 0, input_status_width, input_status_height); + if (command == Minput_status_draw) + { + MDrawMetric rect; + + mtext_put_prop (ic->status, 0, mtext_len (ic->status), + Mface, face_input_status); + if (ic->im->language != Mnil) + mtext_put_prop (ic->status, 0, mtext_len (ic->status), + Mlanguage, ic->im->language); + mdraw_text_extents (frame, ic->status, 0, mtext_len (ic->status), + &input_status_control, NULL, NULL, &rect); + mdraw_text_with_control (frame, (MDrawWindow) input_status_pixmap, + input_status_width - rect.width - 2, - rect.y, + ic->status, 0, mtext_len (ic->status), + &input_status_control); + } + XtSetArg (arg[0], XtNbitmap, input_status_pixmap); + XtSetValues (CurIMStatus, arg, 1); +} + +void +surrounding_text_handler (MInputContext *ic, MSymbol command) +{ + if (command == Minput_get_surrounding_text) + { + int len = (int) mplist_value (ic->plist); + int pos; + MText *surround; + + if (len < 0) + { + pos = cursor.from + len; + if (pos < 0) + pos = 0; + surround = mtext_duplicate (mt, pos, cursor.from); + } + else if (len > 0) + { + pos = cursor.from + len; + if (pos > nchars) + pos = nchars; + surround = mtext_duplicate (mt, cursor.from, pos); + } + else + surround = mtext (); + mplist_set (ic->plist, Mtext, surround); + m17n_object_unref (surround); + } + else if (command == Minput_delete_surrounding_text) + { + int len = (int) mplist_value (ic->plist); + + if (len < 0) + { + if (cursor.from + len < 0) + len = - cursor.from; + mtext_del (mt, cursor.from + len, cursor.from); + nchars += len; + update_cursor (cursor.from + len, 1); + } + else if (len > 0) + { + if (cursor.from + len > nchars) + len = nchars - cursor.from; + mtext_del (mt, cursor.from, cursor.from + len); + nchars -= len; + update_cursor (cursor.from, 1); + } + if (len) + mt_modified = 1; + } +} + +int +compare_input_method (const void *elt1, const void *elt2) +{ + const InputMethodInfo *im1 = elt1; + const InputMethodInfo *im2 = elt2; + MSymbol lang1, lang2; + + if (im1->language == Mnil) + return 1; + if (im1->language == im2->language) + return strcmp (msymbol_name (im1->name), msymbol_name (im2->name)); + if (im1->language == Mt) + return 1; + if (im2->language == Mt) + return -1; + lang1 = mlanguage_name (im1->language); + lang2 = mlanguage_name (im2->language); + return strcmp (msymbol_name (lang1), msymbol_name (lang2)); +} + +void +setup_input_methods (int with_xim, char *initial_input_method) +{ + MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil); + MPlist *pl; + int i; + MSymbol Municode = msymbol ("unicode"); + + num_input_methods = plist ? mplist_length (plist) : 0; + if (with_xim) + num_input_methods++; + input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo)); + + i = 0; + if (plist) + { + for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl), i++) + { + MDatabase *mdb = mplist_value (pl); + MSymbol *tag = mdatabase_tag (mdb); + + if (tag[2] == Mnil) + i--, num_input_methods--; + else + { + input_method_table[i].language = tag[1]; + input_method_table[i].name = tag[2]; + } + } + m17n_object_unref (plist); + } + if (with_xim) + { + input_method_table[i].language = Mnil; + input_method_table[i].name = msymbol ("xim"); + i++; + } + + qsort (input_method_table, num_input_methods, sizeof input_method_table[0], + compare_input_method); + for (i = 0; i < num_input_methods; i++) + if (input_method_table[i].language == Mt + && input_method_table[i].name == Municode) + { + unicode_input_method = i; + break; + } + mplist_put_func (minput_driver->callback_list, Minput_status_start, + M17N_FUNC (input_status)); + mplist_put_func (minput_driver->callback_list, Minput_status_draw, + M17N_FUNC (input_status)); + mplist_put_func (minput_driver->callback_list, Minput_status_done, + M17N_FUNC (input_status)); + mplist_put_func (minput_driver->callback_list, Minput_get_surrounding_text, + M17N_FUNC (surrounding_text_handler)); + mplist_put_func (minput_driver->callback_list, Minput_delete_surrounding_text, + M17N_FUNC (surrounding_text_handler)); + + current_input_context = NULL; + current_input_method = -1; + + if (initial_input_method) + { + char *lang_name, *method_name; + char *p = strchr (initial_input_method, '-'); + + if (p && p[1]) + lang_name = initial_input_method, *p = '\0', method_name = p + 1; + else + lang_name = "t", method_name = initial_input_method; + + for (i = 0; i < num_input_methods; i++) + if ((strcmp (method_name, msymbol_name (input_method_table[i].name)) + == 0) + && (strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0)) + { + current_input_method = i; + break; + } + } +} + + +static void +MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num) +{ + char *msg; + + if (num && *num > 0) + { + int bytes = 0, i; + + for (i = 0; i < *num; i++) + bytes += strlen (str[i]) + 1; + msg = alloca (bytes); + strcpy (msg, str[0]); + for (i = 1; i < *num; i++) + strcat (msg, " "), strcat (msg, str[i]); + } + else if (cursor.from < nchars) + { + int c = mtext_ref_char (mt, cursor.from); + char *name = mchar_get_prop (c, Mname); + + if (! name) + name = ""; + msg = alloca (10 + strlen (name)); + sprintf (msg, "U+%04X %s", c, name); + } + else + { + msg = ""; + } + XtSetArg (arg[0], XtNlabel, msg); + XtSetValues (MessageWidget, arg, 1); +} + +typedef struct +{ + int type; + char *name1, *name2; + XtCallbackProc proc; + XtPointer client_data; + int status; + Widget w; +} MenuRec; + +void PopupProc (Widget w, XtPointer client_data, XtPointer call_data); + +void SaveProc (Widget w, XtPointer client_data, XtPointer call_data); + +MenuRec FileMenu[] = + { { 0, "Open", NULL, PopupProc, FileMenu + 0, -1 }, + { 0, "Save", NULL, SaveProc, NULL, -1 }, + { 0, "Save as", NULL, PopupProc, FileMenu + 2, -1 }, + { 1 }, + { 0, "Serialize", NULL, SerializeProc, (void *) 1, -1 }, + { 0, "Deserialize", NULL, SerializeProc, (void *) 0, -1 }, + { 1 }, + { 0, "Dump Image Buffer", NULL, DumpImageProc, (void *) 0, -1 }, + { 0, "Dump Image Region", NULL, DumpImageProc, (void *) 1, -1 }, + { 1 }, + { 0, "Quit", NULL, QuitProc, NULL, -1 } }; + +void +PopupProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + MenuRec *rec = (MenuRec *) client_data; + Position x, y; + + XtSetArg (arg[0], XtNvalue, ""); + XtSetArg (arg[1], XtNlabel, rec->name1); + XtSetValues (FileDialogWidget, arg, 2); + XtTranslateCoords (w, (Position) 0, (Position) 0, &x, &y); + XtSetArg (arg[0], XtNx, x + 20); + XtSetArg (arg[1], XtNy, y + 10); + XtSetValues (FileShellWidget, arg, 2); + XtPopup (FileShellWidget, XtGrabExclusive); +} + +void +FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + FILE *fp; + char *label; + + XtPopdown (FileShellWidget); + if ((int) client_data == 1) + return; + XtSetArg (arg[0], XtNlabel, &label); + XtGetValues (FileDialogWidget, arg, 1); + if (strcmp (label, FileMenu[0].name1) == 0) + { + /* Open a file */ + free (filename); + filename = strdup ((char *) XawDialogGetValueString (FileDialogWidget)); + fp = fopen (filename, "r"); + hide_cursor (); + m17n_object_unref (mt); + if (fp) + { + mt = mconv_decode_stream (Mcoding_utf_8_full, fp); + fclose (fp); + if (! mt) + mt = mtext (); + } + else + mt = mtext (); + serialized = 0; + nchars = mtext_len (mt); + update_top (0); + update_cursor (0, 1); + redraw (0, win_height, 1, 1); + } + else if (strcmp (label, FileMenu[2].name1) == 0) + SaveProc (w, (XtPointer) XawDialogGetValueString (FileDialogWidget), NULL); + else + fprintf (stderr, "Invalid calling sequence: FileDialogProc\n"); +} + +#define SetMenu(MENU, TYPE, NAME1, NAME2, PROC, DATA, STATUS) \ + ((MENU).type = (TYPE), (MENU).name1 = (NAME1), (MENU).name2 = (NAME2), \ + (MENU).proc = (PROC), (MENU).client_data = (XtPointer) (DATA), \ + (MENU).status = (STATUS)) + + +Widget +create_menu_button (Widget top, Widget parent, Widget left, char *button_name, + char *menu_name, MenuRec *menus, int num_menus, char *help) +{ + Widget button, menu; + char *fmt = ": highlight() MenuHelp(%s)\n\ + : reset() MenuHelp()\n\ + : reset() PopupMenu()\n\ + : highlight()"; + int i; + MenuRec *m; + char *trans; + int max_width = 0; + + menu = XtCreatePopupShell (menu_name, simpleMenuWidgetClass, top, NULL, 0); + for (i = 0; i < num_menus; i++) + { + m = menus + i; + if (m->type == 0) + { + if (m->proc) + { + int n = 0; + + if (m->status >= 0) + { + XtSetArg (arg[n], XtNleftMargin, 20), n++; + if (m->status > 0) + XtSetArg (arg[n], XtNleftBitmap, CheckPixmap), n++; + } + m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass, + menu, arg, n); + XtAddCallback (m->w, XtNcallback, m->proc, m->client_data); + } + else + { + XtSetArg (arg[0], XtNsensitive, False); + m->w = XtCreateManagedWidget (m->name1, smeBSBObjectClass, + menu, arg, 2); + } + } + else + { + XtCreateManagedWidget (m->name1, smeLineObjectClass, menu, NULL, 0); + } + if (m->name2) + max_width = 1; + } + trans = alloca (strlen (fmt) + strlen (help)); + sprintf (trans, fmt, help); + XtSetArg (arg[0], XtNmenuName, menu_name); + XtSetArg (arg[1], XtNtranslations, XtParseTranslationTable ((String) trans)); + XtSetArg (arg[2], XtNinternalWidth, 2); + XtSetArg (arg[3], XtNhighlightThickness, 1); + XtSetArg (arg[4], XtNleft, XawChainLeft); + XtSetArg (arg[5], XtNright, XawChainLeft); + XtSetArg (arg[6], XtNinternational, True); + i = 7; + if (left) + XtSetArg (arg[i], XtNfromHoriz, left), i++; + button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent, + arg, i); + + if (max_width) + { + int height, ascent, *width = alloca (sizeof (int) * num_menus); + int *len = alloca (sizeof (int) * num_menus); + + XFontSet font_set; + XFontSetExtents *fontset_extents; + + XtSetArg (arg[0], XtNfontSet, &font_set); + XtGetValues (button, arg, 1); + + fontset_extents = XExtentsOfFontSet (font_set); + height = fontset_extents->max_logical_extent.height; + ascent = - fontset_extents->max_logical_extent.y; + + for (i = 0; i < num_menus; i++) + if (menus[i].name2) + { + len[i] = strlen (menus[i].name2); + width[i] = XmbTextEscapement (font_set, menus[i].name2, len[i]); + if (max_width < width[i]) + max_width = width[i]; + } + for (i = 0; i < num_menus; i++) + if (menus[i].name2) + { + Pixmap pixmap = XCreatePixmap (display, + RootWindow (display, screen), + max_width, height, 1); + XFillRectangle (display, pixmap, mono_gc_inv, + 0, 0, max_width, height); + XmbDrawString (display, pixmap, font_set, mono_gc, + max_width - width[i], ascent, + menus[i].name2, len[i]); + XtSetArg (arg[0], XtNrightBitmap, pixmap); + XtSetArg (arg[1], XtNrightMargin, max_width + 20); + XtSetValues (menus[i].w, arg, 2); + } + } + + return button; +} + + +XtActionsRec actions[] = { + {"Expose", ExposeProc}, + {"Configure", ConfigureProc}, + {"Key", KeyProc}, + {"ButtonPress", ButtonProc}, + {"ButtonRelease", ButtonReleaseProc}, + {"ButtonMotion", ButtonMoveProc}, + {"Button2Press", Button2Proc}, + {"MenuHelp", MenuHelpProc}, + {"FocusIn", FocusInProc}, + {"FocusOut", FocusOutProc} +}; + + +/* Print the usage of this program (the name is PROG), and exit with + EXIT_CODE. */ + +void +help_exit (char *prog, int exit_code) +{ + char *p = prog; + + while (*p) + if (*p++ == '/') + prog = p; + + printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] FILE\n", prog); + printf ("Display FILE on a window and allow users to edit it.\n"); + printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n"); + printf ("The following OPTIONs are available.\n"); + printf (" %-13s\n\t\t%s", "--fontset FONTSET", + "Use the specified fontset\n"); + printf (" %-13s %s", "-s SIZE", "Font size in 1/10 point (default 120).\n"); + printf (" %-13s\n\t\t%s", "--im INPUT-METHOD", + "Input method activated initially.\n"); + printf (" %-13s %s", "--version", "print version number\n"); + printf (" %-13s %s", "-h, --help", "print this message\n"); + + exit (exit_code); +} + +int +main (int argc, char **argv) +{ + Widget form, BodyWidget, w; + char *fontset_name = NULL; + char *font_name = NULL; + int fontsize = 0; + char *initial_input_method = NULL; + int col = 80, row = 32; + /* Translation table for TextWidget. */ + String trans = ": Expose()\n\ + : Configure()\n\ + : Key()\n\ + : Key()\n\ + : ButtonPress()\n\ + : ButtonRelease()\n\ + : ButtonMotion()\n\ + : Button2Press()"; + /* Translation table for the top form widget. */ + String trans2 = ": Key()\n\ + : Key()\n\ + : FocusIn()\n\ + : FocusOut()"; + String pop_face_trans + = ": MenuHelp(Pop face property) highlight()\n\ + : MenuHelp() reset()\n\ + : set()\n\ + : notify() unset()"; + String pop_lang_trans + = ": MenuHelp(Pop language property) highlight()\n\ + : MenuHelp() reset()\n\ + : set()\n\ + : notify() unset()"; + int font_width, font_ascent, font_descent; + int with_xim = 0; + int i, j; + char *filter = NULL; + MFont *font = NULL; + + setlocale (LC_ALL, ""); + /* Create the top shell. */ + XtSetLanguageProc (NULL, NULL, NULL); + ShellWidget = XtOpenApplication (&context, "M17NEdit", NULL, 0, &argc, argv, + NULL, sessionShellWidgetClass, NULL, 0); + display = XtDisplay (ShellWidget); + screen = XScreenNumberOfScreen (XtScreen (ShellWidget)); + + /* Parse the remaining command line arguments. */ + for (i = 1; i < argc; i++) + { + if (! strcmp (argv[i], "--help") + || ! strcmp (argv[i], "-h")) + help_exit (argv[0], 0); + else if (! strcmp (argv[i], "--version")) + { + printf ("m17n-edit (m17n library) %s\n", M17NLIB_VERSION_NAME); + printf ("Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 AIST, JAPAN\n"); + exit (0); + } + else if (! strcmp (argv[i], "--geometry")) + { + i++; + if (sscanf (argv[i], "%dx%d", &col, &row) != 2) + help_exit (argv[0], 1); + } + else if (! strcmp (argv[i], "-s")) + { + i++; + fontsize = atoi (argv[i]); + if (fontsize < 0) + fontsize = 120; + } + else if (! strcmp (argv[i], "--fontset")) + { + i++; + fontset_name = strdup (argv[i]); + } + else if (! strcmp (argv[i], "--font")) + { + i++; + font_name = strdup (argv[i]); + } + else if (! strcmp (argv[i], "--im")) + { + i++; + initial_input_method = strdup (argv[i]); + } + else if (! strcmp (argv[i], "--with-xim")) + { + with_xim = 1; + } + else if (! strcmp (argv[i], "--filter")) + { + i++; + filter = argv[i]; + } + else if (argv[i][0] != '-') + { + filename = strdup (argv[i]); + } + else + { + fprintf (stderr, "Unknown option: %s\n", argv[i]); + help_exit (argv[0], 1); + } + } + if (! filename) + filename = strdup ("/dev/null"); + + mdatabase_dir = "."; + /* Initialize the m17n library. */ + M17N_INIT (); + if (merror_code != MERROR_NONE) + FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!"); + minput_driver = &minput_gui_driver; + + mt = read_file (filename); + serialized = 0; + + nchars = mtext_len (mt); + + Mword = msymbol ("word"); + + { + MFace *face = mface (); + + mface_put_prop (face, Mforeground, msymbol ("blue")); + mface_put_prop (face, Mbackground, msymbol ("yellow")); + mface_put_prop (face, Mvideomode, Mreverse); + selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE); + m17n_object_unref (face); + } + + /* This tells ExposeProc to initialize everything. */ + top.from = -1; + + XA_TEXT = XInternAtom (display, "TEXT", False); + XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False); + XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False); + Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text")); + if (Mcoding_compound_text == Mnil) + FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!"); + + { + MPlist *plist = mplist (); + MFont *font; + + mplist_put (plist, msymbol ("widget"), ShellWidget); + if (fontset_name || font_name || fontsize > 0) + { + MFace *face; + + if (font_name) + { + font = mfont_parse_name (font_name, Mnil); + if (font) + face = mface_from_font (font); + else + face = mface (); + } + else + face = mface (); + if (fontset_name) + { + MFontset *fontset = mfontset (fontset_name); + + mface_put_prop (face, Mfontset, fontset); + m17n_object_unref (fontset); + } + if (fontsize > 0) + mface_put_prop (face, Msize, (void *) fontsize); + mplist_add (plist, Mface, face); + m17n_object_unref (face); + } + frame = mframe (plist); + if (! frame) + FATAL_ERROR ("%s\n", "Fail to create a frame!"); + m17n_object_unref (plist); + face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface)); + default_face_list = mplist (); + mplist_add (default_face_list, Mt, face_default); + face_default_fontset = mface (); + mface_put_prop (face_default_fontset, Mfontset, + mface_get_prop (face_default, Mfontset)); + + font = (MFont *) mframe_get_prop (frame, Mfont); + default_font_size = (int) mfont_get_prop (font, Msize); + } + + font_width = (int) mframe_get_prop (frame, Mfont_width); + font_ascent = (int) mframe_get_prop (frame, Mfont_ascent); + font_descent = (int) mframe_get_prop (frame, Mfont_descent); + win_width = font_width * col; + win_height = (font_ascent + font_descent) * row; + + { + MFaceBoxProp prop; + + prop.width = 4; + prop.color_top = prop.color_left = msymbol ("magenta"); + prop.color_bottom = prop.color_right = msymbol ("red"); + prop.inner_hmargin = prop.inner_vmargin = 1; + prop.outer_hmargin = prop.outer_vmargin = 2; + + face_box = mface (); + mface_put_prop (face_box, Mbox, &prop); + } + + face_courier = mface (); + mface_put_prop (face_courier, Mfamily, msymbol ("courier")); + face_helvetica = mface (); + mface_put_prop (face_helvetica, Mfamily, msymbol ("helvetica")); + face_times = mface (); + mface_put_prop (face_times, Mfamily, msymbol ("times")); + face_dv_ttyogesh = mface (); + mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh")); + face_freesans = mface (); + mface_put_prop (face_freesans, Mfamily, msymbol ("freesans")); + face_freeserif = mface (); + mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif")); + face_freemono = mface (); + mface_put_prop (face_freemono, Mfamily, msymbol ("freemono")); + + face_xxx_large = mface (); + mface_put_prop (face_xxx_large, Mratio, (void *) 300); + { + MFont *latin_font = mframe_get_prop (frame, Mfont); + MFont *dev_font = mfont (); + MFont *thai_font = mfont (); + MFont *tib_font = mfont (); + MFontset *fontset, *fontset_no_ctl; + MSymbol unicode_bmp = msymbol ("unicode-bmp"); + MSymbol no_ctl = msymbol ("no-ctl"); + + mfont_put_prop (dev_font, Mfamily, msymbol ("raghindi")); + mfont_put_prop (dev_font, Mregistry, unicode_bmp); + mfont_put_prop (thai_font, Mfamily, msymbol ("norasi")); + mfont_put_prop (thai_font, Mregistry, unicode_bmp); + mfont_put_prop (tib_font, Mfamily, msymbol ("mtib")); + mfont_put_prop (tib_font, Mregistry, unicode_bmp); + + fontset = mfontset (fontset_name); + fontset_no_ctl = mfontset_copy (fontset, "no-ctl"); + m17n_object_unref (fontset); + mfontset_modify_entry (fontset_no_ctl, msymbol ("latin"), Mnil, Mnil, + latin_font, Mnil, 0); + mfontset_modify_entry (fontset_no_ctl, msymbol ("devanagari"), Mnil, Mnil, + dev_font, no_ctl, 0); + mfontset_modify_entry (fontset_no_ctl, msymbol ("thai"), Mnil, Mnil, + thai_font, no_ctl, 0); + mfontset_modify_entry (fontset_no_ctl, msymbol ("tibetan"), Mnil, Mnil, + tib_font, no_ctl, 0); + face_no_ctl_fontset = mface (); + mface_put_prop (face_no_ctl_fontset, Mfontset, fontset_no_ctl); + m17n_object_unref (fontset_no_ctl); + + free (dev_font); + free (thai_font); + free (tib_font); + } + + setup_input_methods (with_xim, initial_input_method); + + gc = DefaultGC (display, screen); + + XtSetArg (arg[0], XtNtranslations, XtParseTranslationTable (trans2)); + XtSetArg (arg[1], XtNdefaultDistance, 2); + form = XtCreateManagedWidget ("form", formWidgetClass, ShellWidget, arg, 2); + + XtSetArg (arg[0], XtNborderWidth, 0); + XtSetArg (arg[1], XtNdefaultDistance, 2); + XtSetArg (arg[2], XtNtop, XawChainTop); + XtSetArg (arg[3], XtNbottom, XawChainTop); + XtSetArg (arg[4], XtNleft, XawChainLeft); + XtSetArg (arg[5], XtNright, XawChainRight); + XtSetArg (arg[6], XtNresizable, True); + HeadWidget = XtCreateManagedWidget ("head", formWidgetClass, form, arg, 7); + XtSetArg (arg[7], XtNfromVert, HeadWidget); + FaceWidget = XtCreateManagedWidget ("face", formWidgetClass, form, arg, 8); + XtSetArg (arg[7], XtNfromVert, FaceWidget); + LangWidget = XtCreateManagedWidget ("lang", formWidgetClass, form, arg, 8); + XtSetArg (arg[3], XtNbottom, XawChainBottom); + XtSetArg (arg[7], XtNfromVert, LangWidget); + BodyWidget = XtCreateManagedWidget ("body", formWidgetClass, form, arg, 8); + XtSetArg (arg[2], XtNtop, XawChainBottom); + XtSetArg (arg[7], XtNfromVert, BodyWidget); + TailWidget = XtCreateManagedWidget ("tail", formWidgetClass, form, arg, 8); + + FileShellWidget = XtCreatePopupShell ("FileShell", transientShellWidgetClass, + HeadWidget, NULL, 0); + XtSetArg (arg[0], XtNvalue, ""); + FileDialogWidget = XtCreateManagedWidget ("File", dialogWidgetClass, + FileShellWidget, arg, 1); + XawDialogAddButton (FileDialogWidget, "OK", + FileDialogProc, (XtPointer) 0); + XawDialogAddButton (FileDialogWidget, "CANCEL", + FileDialogProc, (XtPointer) 1); + + CheckPixmap = XCreateBitmapFromData (display, RootWindow (display, screen), + (char *) check_bits, + check_width, check_height); + { + unsigned long valuemask = GCForeground; + XGCValues values; + + values.foreground = 1; + mono_gc = XCreateGC (display, CheckPixmap, valuemask, &values); + values.foreground = 0; + mono_gc_inv = XCreateGC (display, CheckPixmap, valuemask, &values); + } + + { + MenuRec *menus; + int num_menus = 10; + + if (num_menus < num_input_methods + 2) + num_menus = num_input_methods + 2; + if (num_menus < num_faces + 1) + num_menus = num_faces + 1; + menus = alloca (sizeof (MenuRec) * num_menus); + + w = create_menu_button (ShellWidget, HeadWidget, NULL, "File", "File Menu", + FileMenu, sizeof FileMenu / sizeof (MenuRec), + "File I/O, Serialization, Image, Quit"); + + SetMenu (menus[0], 0, "Logical Move", NULL, CursorProc, 0, 1); + SetMenu (menus[1], 0, "Visual Move", NULL, CursorProc, 1, 0); + SetMenu (menus[2], 1, "", NULL, NULL, NULL, 0); + SetMenu (menus[3], 0, "Box type", NULL, CursorProc, 2, 0); + SetMenu (menus[4], 0, "Bar type", NULL, CursorProc, 3, 1); + SetMenu (menus[5], 0, "Bidi type", NULL, CursorProc, 4, 0); + w = create_menu_button (ShellWidget, HeadWidget, w, + "Cursor", "Cursor Menu", + menus, 6, "Cursor Movement Mode, Cursor Shape"); + CursorMenus[0] = menus[0].w; + CursorMenus[1] = menus[1].w; + CursorMenus[2] = menus[3].w; + CursorMenus[3] = menus[4].w; + CursorMenus[4] = menus[5].w; + + SetMenu (menus[0], 0, "disable", NULL, BidiProc, 0, 0); + SetMenu (menus[1], 0, "Left (|--> |)", NULL, BidiProc, 1, 1); + SetMenu (menus[2], 0, "Right (| <--|)", NULL, BidiProc, 2, 0); + w = create_menu_button (ShellWidget, HeadWidget, w, "Bidi", "Bidi Menu", + menus, 3, "BIDI Processing Mode"); + for (i = 0; i < 3; i++) + BidiMenus[i] = menus[i].w; + + SetMenu (menus[0], 0, "truncate", NULL, LineBreakProc, 0, 0); + SetMenu (menus[1], 0, "break at edge", NULL, LineBreakProc, 1, 1); + SetMenu (menus[2], 0, "break at word boundary", NULL, LineBreakProc, 2, 0); + w = create_menu_button (ShellWidget, HeadWidget, w, "LineBreak", + "LineBreak Menu", + menus, 3, "How to break lines"); + for (i = 0; i < 3; i++) + LineBreakMenus[i] = menus[i].w; + + SetMenu (menus[0], 0, "none", NULL, InputMethodProc, -2, 1); + SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0); + for (i = 0; i < num_input_methods; i++) + { + InputMethodInfo *im = input_method_table + i; + char *name1, *name2; + + if (im->language != Mnil && im->language != Mt) + { + MSymbol sym = mlanguage_name (im->language); + if (sym == Mnil) + name1 = msymbol_name (im->language); + else + name1 = msymbol_name (sym); + name2 = msymbol_name (im->name); + } + else + name1 = msymbol_name (im->name), name2 = NULL; + + SetMenu (menus[i + 2], 0, name1, name2, InputMethodProc, i, 0); + } + w = create_menu_button (ShellWidget, HeadWidget, w, "InputMethod", + "Input Method Menu", menus, i + 2, + "Select input method"); + + { + unsigned long valuemask = GCForeground; + XGCValues values; + + XtSetArg (arg[0], XtNbackground, &values.foreground); + XtGetValues (w, arg, 1); + gc_inv = XCreateGC (display, RootWindow (display, screen), + valuemask, &values); + } + + InputMethodMenus = malloc (sizeof (Widget) * (num_input_methods + 2)); + for (i = 0; i < num_input_methods + 2; i++) + InputMethodMenus[i] = menus[i].w; + + if (filter) + { + SetMenu (menus[0], 0, filter, NULL, FilterProc, filter, 0); + w = create_menu_button (ShellWidget, HeadWidget, w, "Filter", + "Filter Menu", menus, 1, + "Select filter to run"); + } + + input_status_width = font_width * 8; + input_status_height = (font_ascent + font_descent) * 2.4; + input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen), + input_status_width, + input_status_height, + DefaultDepth (display, screen)); + { + MFaceBoxProp prop; + + prop.width = 1; + prop.color_top = prop.color_bottom + = prop.color_left = prop.color_right = Mnil; + prop.inner_hmargin = prop.inner_vmargin = 1; + prop.outer_hmargin = prop.outer_vmargin = 0; + face_input_status = mface_copy (face_default); + mface_put_prop (face_input_status, Mbox, &prop); + } + + XFillRectangle (display, input_status_pixmap, gc_inv, + 0, 0, input_status_width, input_status_height); + XtSetArg (arg[0], XtNfromHoriz, w); + XtSetArg (arg[1], XtNleft, XawRubber); + XtSetArg (arg[2], XtNright, XawChainRight); + XtSetArg (arg[3], XtNborderWidth, 0); + XtSetArg (arg[4], XtNlabel, " "); + XtSetArg (arg[5], XtNjustify, XtJustifyRight); + CurIMLang = XtCreateManagedWidget ("CurIMLang", labelWidgetClass, + HeadWidget, arg, 6); + XtSetArg (arg[0], XtNfromHoriz, CurIMLang); + XtSetArg (arg[1], XtNleft, XawChainRight); + XtSetArg (arg[4], XtNbitmap, input_status_pixmap); + CurIMStatus = XtCreateManagedWidget ("CurIMStatus", labelWidgetClass, + HeadWidget, arg, 5); + + XtSetArg (arg[0], XtNborderWidth, 0); + XtSetArg (arg[1], XtNleft, XawChainLeft); + XtSetArg (arg[2], XtNright, XawChainLeft); + w = XtCreateManagedWidget ("Face", labelWidgetClass, FaceWidget, arg, 3); + for (i = 0; i < num_faces;) + { + char *label_menu = face_table[i++].name; /* "Menu Xxxx" */ + char *label = label_menu + 5; /* "Xxxx" */ + + for (j = i; j < num_faces && face_table[j].face; j++) + SetMenu (menus[j - i], 0, face_table[j].name, NULL, + FaceProc, j, -1); + w = create_menu_button (ShellWidget, FaceWidget, w, + label, label_menu, + menus, j - i, "Push face property"); + i = j; + } + + XtSetArg (arg[0], XtNfromHoriz, w); + XtSetArg (arg[1], XtNleft, XawChainLeft); + XtSetArg (arg[2], XtNright, XawChainLeft); + XtSetArg (arg[3], XtNhorizDistance, 10); + XtSetArg (arg[4], XtNlabel, "Pop"); + XtSetArg (arg[5], XtNtranslations, + XtParseTranslationTable (pop_face_trans)); + w = XtCreateManagedWidget ("Pop Face", commandWidgetClass, + FaceWidget, arg, 6); + XtAddCallback (w, XtNcallback, FaceProc, (void *) -1); + + XtSetArg (arg[0], XtNfromHoriz, w); + XtSetArg (arg[1], XtNleft, XawChainLeft); + XtSetArg (arg[2], XtNright, XawChainRight); + XtSetArg (arg[3], XtNlabel, ""); + XtSetArg (arg[4], XtNborderWidth, 0); + XtSetArg (arg[5], XtNjustify, XtJustifyRight); + CurFaceWidget = XtCreateManagedWidget ("Current Face", labelWidgetClass, + FaceWidget, arg, 6); + + XtSetArg (arg[0], XtNborderWidth, 0); + XtSetArg (arg[1], XtNleft, XawChainLeft); + XtSetArg (arg[2], XtNright, XawChainLeft); + w = XtCreateManagedWidget ("Lang", labelWidgetClass, LangWidget, arg, 3); + { + MPlist *plist[11], *pl; + char langname[3]; + + for (i = 0; i < 11; i++) plist[i] = NULL; + langname[2] = '\0'; + for (langname[0] = 'a'; langname[0] <= 'z'; langname[0]++) + for (langname[1] = 'a'; langname[1] <= 'z'; langname[1]++) + { + MSymbol sym = msymbol_exist (langname); + MSymbol fullname; + + if (sym != Mnil + && ((fullname = mlanguage_name (sym)) != Mnil)) + { + char *name = msymbol_name (fullname); + char c = name[0]; + + if (c >= 'a' && c <= 'z') + { + int idx = (c < 'u') ? (c - 'a') / 2 : 10; + + pl = plist[idx]; + if (! pl) + pl = plist[idx] = mplist (); + for (; mplist_next (pl); pl = mplist_next (pl)) + if (strcmp (name, (char *) mplist_value (pl)) < 0) + break; + mplist_push (pl, sym, fullname); + } + } + } + + for (i = 0; i < 11; i++) + if (plist[i]) + { + char *name = alloca (9); + + sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1); + if (i == 10) + name[7] = 'Z'; + for (j = 0, pl = plist[i]; mplist_next (pl); + j++, pl = mplist_next (pl)) + SetMenu (menus[j], 0, msymbol_name ((MSymbol) mplist_value (pl)), + msymbol_name (mplist_key (pl)), + LangProc, mplist_key (pl), -1); + w = create_menu_button (ShellWidget, LangWidget, w, name + 5, name, + menus, j, "Push language property"); + } + for (i = 0; i < 11; i++) + if (plist[i]) + m17n_object_unref (plist[i]); + } + XtSetArg (arg[0], XtNfromHoriz, w); + XtSetArg (arg[1], XtNleft, XawChainLeft); + XtSetArg (arg[2], XtNright, XawChainLeft); + XtSetArg (arg[3], XtNhorizDistance, 10); + XtSetArg (arg[4], XtNlabel, "Pop"); + XtSetArg (arg[5], XtNtranslations, + XtParseTranslationTable (pop_lang_trans)); + w = XtCreateManagedWidget ("Pop Lang", commandWidgetClass, + LangWidget, arg, 6); + XtAddCallback (w, XtNcallback, LangProc, Mnil); + + XtSetArg (arg[0], XtNfromHoriz, w); + XtSetArg (arg[1], XtNleft, XawChainLeft); + XtSetArg (arg[2], XtNright, XawChainRight); + XtSetArg (arg[3], XtNlabel, ""); + XtSetArg (arg[4], XtNborderWidth, 0); + XtSetArg (arg[5], XtNjustify, XtJustifyRight); + CurLangWidget = XtCreateManagedWidget ("Current Lang", labelWidgetClass, + LangWidget, arg, 6); + } + + XtSetArg (arg[0], XtNheight, win_height); + XtSetArg (arg[1], XtNwidth, 10); + XtSetArg (arg[2], XtNleft, XawChainLeft); + XtSetArg (arg[3], XtNright, XawChainLeft); + SbarWidget = XtCreateManagedWidget ("sbar", scrollbarWidgetClass, BodyWidget, + arg, 4); + XtAddCallback (SbarWidget, XtNscrollProc, ScrollProc, NULL); + XtAddCallback (SbarWidget, XtNjumpProc, JumpProc, NULL); + + XtSetArg (arg[0], XtNheight, win_height); + XtSetArg (arg[1], XtNwidth, win_width); + XtSetArg (arg[2], XtNtranslations, XtParseTranslationTable (trans)); + XtSetArg (arg[3], XtNfromHoriz, SbarWidget); + XtSetArg (arg[4], XtNleft, XawChainLeft); + XtSetArg (arg[5], XtNright, XawChainRight); + TextWidget = XtCreateManagedWidget ("text", simpleWidgetClass, BodyWidget, + arg, 5); + + XtSetArg (arg[0], XtNborderWidth, 0); + XtSetArg (arg[1], XtNleft, XawChainLeft); + XtSetArg (arg[2], XtNright, XawChainRight); + XtSetArg (arg[3], XtNresizable, True); + XtSetArg (arg[4], XtNjustify, XtJustifyLeft); + MessageWidget = XtCreateManagedWidget ("message", labelWidgetClass, + TailWidget, arg, 5); + + memset (&control, 0, sizeof control); + control.two_dimensional = 1; + control.enable_bidi = 1; + control.anti_alias = 1; + control.min_line_ascent = font_ascent; + control.min_line_descent = font_descent; + control.max_line_width = win_width; + control.with_cursor = 1; + control.cursor_width = 2; + control.partial_update = 1; + control.ignore_formatting_char = 1; + + memset (&input_status_control, 0, sizeof input_status_control); + input_status_control.enable_bidi = 1; + + XtAppAddActions (context, actions, XtNumber (actions)); + XtRealizeWidget (ShellWidget); + + win = XtWindow (TextWidget); + + XtAppMainLoop (context); + + if (current_input_context) + minput_destroy_ic (current_input_context); + for (i = 0; i < num_input_methods; i++) + if (input_method_table[i].im) + minput_close_im (input_method_table[i].im); + m17n_object_unref (frame); + m17n_object_unref (mt); + m17n_object_unref (face_xxx_large); + m17n_object_unref (face_box); + m17n_object_unref (face_courier); + m17n_object_unref (face_helvetica); + m17n_object_unref (face_times); + m17n_object_unref (face_dv_ttyogesh); + m17n_object_unref (face_freesans); + m17n_object_unref (face_freeserif); + m17n_object_unref (face_freemono); + m17n_object_unref (face_default_fontset); + m17n_object_unref (face_no_ctl_fontset); + m17n_object_unref (face_input_status); + m17n_object_unref (face_default); + m17n_object_unref (default_face_list); + m17n_object_unref (selection); + if (font) + free (font); + + XFreeGC (display, mono_gc); + XFreeGC (display, mono_gc_inv); + XFreeGC (display, gc_inv); + XtUninstallTranslations (form); + XtUninstallTranslations (TextWidget); + XtDestroyWidget (ShellWidget); + XtDestroyApplicationContext (context); + + M17N_FINI (); + + free (font_name); + free (fontset_name); + free (filename); + free (input_method_table); + free (InputMethodMenus); + + exit (0); +} + +#else /* not HAVE_X11_XAW_COMMAND_H */ + +int +main (int argc, char **argv) +{ + fprintf (stderr, + "Building of this program failed (lack of some header files)\n"); + exit (1); +} + +#endif /* not HAVE_X11_XAW_COMMAND_H */ + +#endif /* not FOR_DOXYGEN */ diff --git a/example/mimx-anthy.c b/example/mimx-anthy.c new file mode 100644 index 0000000..bc199ca --- /dev/null +++ b/example/mimx-anthy.c @@ -0,0 +1,394 @@ +/* mimx-anthy.c -- Anthy input method external module. -*- coding: euc-jp; -*- + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @enpage mimx-anthy external module for the input method + + @section mimx-anthy-description DESCRIPTION + + The shared library mimx-anthy.so is an external module used by the + input method . It exports these functions. + +
    +
  • init + + Initialize this module. + +
  • fini + + Finalize this module. + +
  • convert + + Convert the current preedit text (Hiragana sequence) into + Kana-Kanji mixed text. + +
  • change + + Record the change of candidate of the current segment. + +
  • resize + + Enlarge or shorten the length of the current segment. + +
  • commit + + Commit the lastly selected candidates of all the segments. + +
+ + @section mimx-anthy-seealso See also + @ref mdbIM +*/ +/***ja + @japage mimx-anthy ���ϥ᥽�å� �ѳ����⥸�塼��. + + @section mimx-anthy-description DESCRIPTION + + ��ͭ�饤�֥�� mimx-anthy.so �����ϥ᥽�å� ���Ѥ���� + �볰���⥸�塼��Ǥ��ꡢ�ʲ��δؿ��� export ���Ƥ��롣 + +
    +
  • init + + �⥸�塼��ν������ + +
  • fini + + �⥸�塼��ν�λ�� + +
  • convert + + ���ߤ� preedit �ƥ����� (�Ҥ餬����) �򤫤ʴ����ƥ����Ȥ��Ѵ����롣 + +
  • change + + ���ߤΥ������Ȥθ����������Ͽ���롣 + +
  • resize + + ���ߤΥ������Ȥ�Ĺ�����ѹ����롣 + +
  • commit + + ���������Ȥκǿ��θ���򥳥ߥåȤ��롣 + +
+ + @section mimx-anthy-seealso ���� + @ref mdbIM +*/ + +#ifndef FOR_DOXYGEN + +#include +#include +#include + +#ifdef HAVE_ANTHY + +#include + +static int initialized; +static MSymbol Manthy, Msegment; + +/* A structure to record in MInputContext->plist with key Manthy. */ + +typedef struct { + MInputContext *ic; + anthy_context_t ac; + /* Which candidate is selected in each segment. */ + int *candidate_numbers; + /* Size of the above array. */ + int num_segments; + /* Converter for this context. */ + MConverter *converter; +} AnthyContext; + +static AnthyContext * +new_context (MInputContext *ic) +{ + AnthyContext *context; + anthy_context_t ac; + MSymbol euc_jp = msymbol ("euc-jp"); + /* Rebound to an actual buffer just before being used. */ + MConverter *converter = mconv_buffer_converter (euc_jp, NULL, 0); + + if (! converter) + return NULL; + ac = anthy_create_context (); + if (! ac) + return NULL; + context = calloc (1, sizeof (AnthyContext)); + context->ic = ic; + context->ac = ac; + context->num_segments = 0; + context->candidate_numbers = NULL; + context->converter = converter; + return context; +} + +static AnthyContext * +get_context (MInputContext *ic) +{ + MPlist *plist = ic->plist; + AnthyContext *context; + + for (; plist && mplist_key (plist) != Mnil; plist = mplist_next (plist)) + { + if (mplist_key (plist) != Manthy) + continue; + context = mplist_value (plist); + if (context->ic == ic) + return context; + } + return NULL; +} + + +static void +free_context (AnthyContext *context) +{ + anthy_release_context (context->ac); + if (context->candidate_numbers) + free (context->candidate_numbers); + mconv_free_converter (context->converter); + free (context); +} + +static void +allocate_candidate_numbers (AnthyContext *context, int num) +{ + if (context->num_segments < num) + { + if (context->num_segments == 0) + context->candidate_numbers = malloc (sizeof (int) * num); + else + context->candidate_numbers = realloc (context->candidate_numbers, + sizeof (int) * num); + context->num_segments = num; + } +} + +static void +add_action (MPlist *actions, MSymbol name, MSymbol key, void *val) +{ + MPlist *action = mplist (); + + mplist_add (action, Msymbol, name); + mplist_add (action, key, val); + mplist_add (actions, Mplist, action); + m17n_object_unref (action); +} + +/* Return a list of all candidates of the Nth segment. The return + value is a plist whose elements are plists who contains at most 5 + candidates. */ + +static MPlist * +make_candidate_list (AnthyContext *context, int n) +{ + MPlist *plist = mplist (), *pl; + int i; + char buf[1024]; + struct anthy_segment_stat ss; + MText *mt; + + anthy_get_segment_stat (context->ac, n, &ss); + for (i = 0, pl = mplist (); i < ss.nr_candidate; i++) + { + anthy_get_segment (context->ac, n, i, buf, sizeof (buf)); + mconv_rebind_buffer (context->converter, + (unsigned char *) buf, strlen (buf)); + mt = mconv_decode (context->converter, mtext ()); + mtext_put_prop (mt, 0, mtext_len (mt), Msegment, (void *) (n + 1)); + mplist_add (pl, Mtext, mt); + m17n_object_unref (mt); + if (i % 5 == 4) + { + mplist_add (plist, Mplist, pl); + m17n_object_unref (pl); + pl = mplist (); + } + } + if (mplist_key (pl) != Mnil) + mplist_add (plist, Mplist, pl); + m17n_object_unref (pl); + return plist; +} + +MPlist * +init (MPlist *args) +{ + MInputContext *ic = mplist_value (args); + AnthyContext *context; + + if (! initialized++) + { + anthy_init (); + Manthy = msymbol (" anthy"); + Msegment = msymbol (" segment"); + } + context = new_context (ic); + if (context) + mplist_push (ic->plist, Manthy, context); + return NULL; +} + +MPlist * +fini (MPlist *args) +{ + MInputContext *ic = mplist_value (args); + AnthyContext *context = get_context (ic); + + if (context) + free_context (context); + return NULL; +} + +MPlist * +convert (MPlist *args) +{ + MInputContext *ic = mplist_value (args); + AnthyContext *context = get_context (ic); + struct anthy_conv_stat cs; + MPlist *action, *actions; + int i; + unsigned char buf[1024]; + + if (! context) + return NULL; + + mconv_rebind_buffer (context->converter, buf, sizeof (buf)); + mconv_encode (context->converter, ic->preedit); + buf[context->converter->nbytes] = '\0'; + anthy_set_string (context->ac, (char *) buf); + anthy_get_stat (context->ac, &cs); + allocate_candidate_numbers (context, cs.nr_segment); + + actions = mplist (); + add_action (actions, msymbol ("move"), Msymbol, msymbol ("@<")); + add_action (actions, msymbol ("delete"), Msymbol, msymbol ("@>")); + for (i = 0; i < cs.nr_segment; i++) + { + context->candidate_numbers[i] = 0; + if (i == 1) + add_action (actions, msymbol ("mark"), Msymbol, msymbol ("@anthy")); + action = make_candidate_list (context, i); + mplist_add (actions, Mplist, action); + m17n_object_unref (action); + } + if (cs.nr_segment > 1) + add_action (actions, msymbol ("move"), Msymbol, msymbol ("@anthy")); + + return actions; +} + +MPlist * +change (MPlist *args) +{ + MInputContext *ic = mplist_value (args); + AnthyContext *context = get_context (ic); + int segment; + + if (! context) + return NULL; + if (! ic->candidate_list || ic->cursor_pos == 0) + return NULL; + segment = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1, Msegment); + if (segment == 0) + return NULL; + segment--; + context->candidate_numbers[segment] = ic->candidate_index; + return NULL; +} + +MPlist * +resize (MPlist *args) +{ + MInputContext *ic = mplist_value (args); + AnthyContext *context = get_context (ic); + struct anthy_conv_stat cs; + MSymbol shorten; + int segment; + MPlist *actions, *action; + int i; + + if (! context) + return NULL; + if (! ic->candidate_list || ic->cursor_pos == 0) + return NULL; + segment = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1, Msegment); + if (segment == 0) + return NULL; + segment--; + args = mplist_next (args); + shorten = mplist_value (args); + anthy_resize_segment (context->ac, segment, shorten == Mt ? -1 : 1); + anthy_get_stat (context->ac, &cs); + allocate_candidate_numbers (context, cs.nr_segment); + + actions = mplist (); + if (segment == 0) + add_action (actions, msymbol ("move"), Msymbol, msymbol ("@<")); + else + add_action (actions, msymbol ("move"), Msymbol, msymbol ("@[")); + add_action (actions, msymbol ("delete"), Msymbol, msymbol ("@>")); + for (i = segment; i < cs.nr_segment; i++) + { + context->candidate_numbers[i] = 0; + if (i == segment + 1) + add_action (actions, msymbol ("mark"), Msymbol, msymbol ("@anthy")); + action = make_candidate_list (context, i); + mplist_add (actions, Mplist, action); + m17n_object_unref (action); + } + if (segment + 1 < cs.nr_segment) + add_action (actions, msymbol ("move"), Msymbol, msymbol ("@anthy")); + return actions; +} + +MPlist * +commit (MPlist *args) +{ + MInputContext *ic = mplist_value (args); + AnthyContext *context = get_context (ic); + struct anthy_conv_stat cs; + int i; + + if (! context) + return NULL; + anthy_get_stat (context->ac, &cs); + for (i = 0; i < cs.nr_segment; i++) + anthy_commit_segment (context->ac, i, context->candidate_numbers[i]); + return NULL; +} + +#else /* not HAVE_ANTHY */ + +MPlist *convert (MPlist *args) { return NULL; } +MPlist *change (MPlist *args) { return NULL; } +MPlist *resize (MPlist *args) { return NULL; } +MPlist *commit (MPlist *args) { return NULL; } + +#endif /* not HAVE_ANTHY */ +#endif /* not FOR_DOXYGEN */ diff --git a/example/mimx-ispell.c b/example/mimx-ispell.c new file mode 100644 index 0000000..0945896 --- /dev/null +++ b/example/mimx-ispell.c @@ -0,0 +1,241 @@ +/* imx-ispell.c -- Ispell input method external module. -*- coding: euc-jp; -*- + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @enpage mimx-ispell external module for the input method + + @section mimx-ispell-description DESCRIPTION + + The shared library mimx-ispell.so is an external module used by the + input method . It exports these functions. + +
    +
  • init + + Initialize this library. + +
  • fini + + Finalize this library. + +
  • ispell_word + + Check the spell of the current preedit text (English) and, if the + spell is incorrect, return a list of candidates. + +
+ + This program is just for demonstrating how to write an external + module for an m17n input method, not for an actual use. + + @section mimx-ispell-seealso See also + @ref mdbIM +*/ +/***ja + @japage mimx-ispell ���ϥ᥽�å� �ѳ����⥸�塼�� + + @section mimx-ispell-description DESCRIPTION + + ��ͭ�饤�֥�� mimx-ispell.so �����ϥ᥽�å� ���Ѥ��� + ��볰���⥸�塼��Ǥ��ꡢ�ʲ��δؿ��� export ���Ƥ��롣 + +
    +
  • init + + �饤�֥��ν������ + +
  • fini + + �饤�֥��ν�λ�� + +
  • ispell_word + + ���ߤ� preedit �ƥ����� (��ʸ) ���֤�Ĵ�١��ְ�äƤ���и���Υ� + ���Ȥ��֤��� + +
+ + ���Υץ�������m17n ���ϥ᥽�å��ѳ����⥸�塼��ν����򼨤��� + ��Τ�ΤǤ��ꡢ�ºݤ����Ѥ�տޤ�����ΤǤϤʤ��� + + @section mimx-ispell-seealso ���� + @ref mdbIM +*/ + +#ifndef FOR_DOXYGEN + +#include +#include +#include + +#ifdef HAVE_ISPELL + +static int initialized = 0; +static int face_available; +static MFace *mface_overstrike = NULL; + +static MPlist * +add_action (MPlist *actions, MSymbol name, MSymbol key, void *val) +{ + MPlist *action = mplist (); + + mplist_add (action, Msymbol, name); + if (key != Mnil) + mplist_add (action, key, val); + mplist_add (actions, Mplist, action); + m17n_object_unref (action); + return actions; +} + +MPlist * +init (MPlist *args) +{ + if (! initialized++) + { + MFaceHLineProp hline; + + face_available = 0; + if (m17n_status () == M17N_GUI_INITIALIZED) + { + face_available = 1; + hline.type = MFACE_HLINE_STRIKE_THROUGH; + hline.width = 1; + hline.color = msymbol ("black"); + mface_overstrike = mface (); + mface_put_prop (mface_overstrike, Mhline, &hline); + } + } + return NULL; +} + +MPlist * +fini (MPlist *args) +{ + if (initialized != 0 + && --initialized == 0 + && face_available) + m17n_object_unref (mface_overstrike); + return NULL; +} + +MPlist * +ispell_word (MPlist *args) +{ + MInputContext *ic; + unsigned char buf[256]; + int nbytes; + MPlist *actions, *candidates, *plist; + char command[256]; + char **words; + FILE *ispell; + char *p = (char *) buf; + int i, n; + MSymbol init_state; + MSymbol select_state; + MText *mt; + + ic = mplist_value (args); + args = mplist_next (args); + init_state = (MSymbol) mplist_value (args); + args = mplist_next (args); + select_state = (MSymbol) mplist_value (args); + nbytes = mconv_encode_buffer (Mcoding_us_ascii, ic->preedit, buf, 256); + + actions = mplist (); + + if (nbytes < 3) + return add_action (actions, msymbol ("shift"), Msymbol, init_state); + + buf[nbytes] = '\0'; + sprintf (command, "echo %s | ispell -a -m", (char *) buf); + ispell = popen (command, "r"); + if (! ispell) + return add_action (actions, msymbol ("shift"), Msymbol, init_state); + + /* Skip the heading line. */ + fgets (p, 256, ispell); + /* Read just 256 bytes, thus candidates listed after the first 256 + bytes are just ignored. */ + fgets (p, 256, ispell); + pclose (ispell); + p[strlen (p) - 1] = '\0'; + if (*p != '&' && *p != '#') + return add_action (actions, msymbol ("shift"), Msymbol, init_state); + + add_action (actions, msymbol ("delete"), Msymbol, msymbol ("@<")); + if (*p == '#') + { + mt = mtext_dup (ic->preedit); + if (face_available) + mtext_push_prop (mt, 0, mtext_len (mt), Mface, mface_overstrike); + mplist_add (actions, Mtext, mt); + add_action (actions, msymbol ("shift"), Msymbol, init_state); + m17n_object_unref (mt); + return actions; + } + + p = strchr (p + 2, ' '); + if (sscanf (p, "%d", &n) != 1) + return add_action (actions, msymbol ("shift"), Msymbol, init_state); + words = alloca (sizeof (char *) * n); + p = strchr (p + 1, ' '); + p = strchr (p + 1, ' '); + for (i = 0; i < n - 1; i++) + { + words[i] = ++p; + p = strchr (p, ','); + if (! p) + { + n = i - 1; + break; + } + *p++ = '\0'; + } + words[i] = ++p; + candidates = mplist (); + for (i = 0; i < n; i++) + { + mt = mconv_decode_buffer (Mcoding_us_ascii, (unsigned char *) words[i], + strlen (words[i])); + mplist_add (candidates, Mtext, mt); + m17n_object_unref (mt); + } + mt = mtext_dup (ic->preedit); + if (face_available) + mtext_push_prop (mt, 0, mtext_len (mt), Mface, mface_overstrike); + mplist_add (candidates, Mtext, mt); + m17n_object_unref (mt); + plist = mplist_add (mplist (), Mplist, candidates); + m17n_object_unref (candidates); + mplist_add (actions, Mplist, plist); + m17n_object_unref (plist); + add_action (actions, msymbol ("show"), Mnil, NULL); + add_action (actions, msymbol ("shift"), Msymbol, select_state); + return actions; +} + +#else /* not HAVE_ISPELL */ + +MPlist *ispell_word (MPlist *args) { return NULL; } + +#endif /* not HAVE_ISPELL */ +#endif /* not FOR_DOXYGEN */ diff --git a/example/mview.c b/example/mview.c new file mode 100644 index 0000000..5165332 --- /dev/null +++ b/example/mview.c @@ -0,0 +1,438 @@ +/* mview.c -- File viewer -*- coding: euc-jp; -*- + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @enpage m17n-view view file + + @section m17n-view-synopsis SYNOPSIS + + m17n-view [ XT-OPTION ...] [ OPTION ... ] [ FILE ] + + @section m17n-view-description DESCRIPTION + + Display FILE on a window. + + If FILE is omitted, the input is taken from standard input. + + XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg). + + The following OPTIONs are available. + +
    + +
  • -e ENCODING + + ENCODING is the encoding of FILE (defaults to UTF-8). + +
  • -s FONTSIZE + + FONTSIZE is the fontsize in point. If omitted, it defaults to the + size of the default font defined in X resource. + +
  • --version + + Print version number. + +
  • -h, --help + + Print this message. + +
+*/ +/***ja + @japage m17n-view �ե�����򸫤� + + @section m17n-view-synopsis SYNOPSIS + + m17n-view [ XT-OPTION ...] [ OPTION ... ] [ FILE ] + + @section m17n-view-description DESCRIPTION + + FILE �򥦥���ɥ���ɽ�����롣 + + FILE ����ά���줿���ϡ�ɸ�����Ϥ���Ȥ롣 + + XT-OPTIONs �� Xt ��ɸ��ΰ����Ǥ��롣 (e.g. -fn, -fg). + + �ʲ��Υ��ץ�������ѤǤ��롣 + +
    + +
  • -e ENCODING + + ENCODING �� FILE �Υ����ɷϤǤ��롣(�ǥե���Ȥ� UTF-8) + +
  • -s FONTSIZE + + FONTSIZE �ϥե���Ȥ��礭����ݥ����ñ�̤Ǽ�������ΤǤ��롣��ά + ���줿���ϡ�X �Υ꥽������������줿�ǥե���ȥե���Ȥ��礭���� + �ʤ롣 + +
  • --version + + �С�������ֹ��ɽ�����롣 + +
  • -h, --help + + ���Υ�å�������ɽ�����롣 + +
+*/ +#ifndef FOR_DOXYGEN + +#include +#include + +#ifdef HAVE_X11_XAW_COMMAND_H + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +/* Global m17n variables. */ +MFrame *frame; +MText *mt; +MDrawMetric metric; +MDrawControl control; + + +/* Callback procedure for "quit". */ + +void +QuitProc (Widget w, XtPointer client_data, XtPointer call_data) +{ + XtAppSetExitFlag (XtWidgetToApplicationContext (w)); +} + + +/* Move POS to the next line head in M-text MT whose length is LEN. + If POS is already on the last line, set POS to LEN. */ + +#define NEXTLINE(pos, len) \ + do { \ + pos = mtext_character (mt, pos, len, '\n'); \ + if (pos < 0) \ + pos = len; \ + else \ + pos++; \ + } while (0) + + +/* Action procedure for expose event. Redraw partial area of the + widget W. The area is specified in EVENT. */ + +static void +ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num) +{ + XExposeEvent *expose = (XExposeEvent *) event; + int len = mtext_len (mt); + int pos, from, to; + int y = 0, yoff = 0; + MDrawMetric rect; + + /* We must update the area between the Y-positions expose->y and + (expose->y + expose->height). We ignore X-positions. */ + + /* At first, find the line that occupies the Y-position expose->y. + That is the first line to draw. */ + to = 0; + while (1) + { + from = to; + NEXTLINE (to, len); + mdraw_text_extents (frame, mt, from, to, &control, NULL, NULL, &rect); + if (to == len || y + rect.height > expose->y) + break; + y += rect.height; + } + /* The first character to draw is at position FROM. Remeber the + Y-position to start drawing. */ + yoff = y - rect.y; + + /* Next, find the line that occupies the Y-position (expose->y + + expose->height). That is the last line to draw. This time, we + enable caching to utilize it in the later drawing. */ + y += rect.height; + control.disable_caching = 0; + while (to < len && y < expose->y + expose->height) + { + pos = to; + NEXTLINE (to, len); + mdraw_text_extents (frame, mt, pos, to, &control, NULL, NULL, &rect); + y += rect.height; + } + + /* It is decided that we must draw from FROM to the previous + character of TO. */ + mdraw_text_with_control (frame, (MDrawWindow) XtWindow (w), + 0, yoff, mt, from, to, &control); + + /* Disable caching again. */ + control.disable_caching = 1; + + /* If the widget was vertically enlarged too much, shrink it. */ + if (metric.height < expose->y + expose->height) + { + Arg arg; + + XtSetArg (arg, XtNheight, metric.height); + XtSetValues (w, &arg, 0); + } +} + + +/* Print the usage of this program (the name is PROG), and exit with + EXIT_CODE. */ + +void +help_exit (char *prog, int exit_code) +{ + char *p = prog; + + while (*p) + if (*p++ == '/') + prog = p; + + printf ("Usage: %s [ XT-OPTION ...] [ OPTION ...] [ FILE ]\n", prog); + printf ("Display FILE on a window.\n"); + printf (" If FILE is omitted, the input is taken from standard input.\n"); + printf (" XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n"); + printf ("The following OPTIONs are available.\n"); + printf (" %-13s %s", "-e ENCODING", + "ENCODING is the encoding of FILE (defaults to UTF-8).\n"); + printf (" %-13s %s", "-s FONTSIZE", + "FONTSIZE is the fontsize in point.\n"); + printf ("\t\tIf omitted, it defaults to the size\n"); + printf ("\t\tof the default font defined in X resource.\n"); + printf (" %-13s %s", "--version", "print version number\n"); + printf (" %-13s %s", "-h, --help", "print this message\n"); + exit (exit_code); +} + + +/* Format MSG by FMT and print the result to the stderr, and exit. */ + +#define FATAL_ERROR(fmt, arg) \ + do { \ + fprintf (stderr, fmt, arg); \ + exit (1); \ + } while (0) + + +/* Adjust FONTSIZE for the resolution of the screen of widget W. */ + +int +adjust_fontsize (Widget w, int fontsize) +{ + Display *display = XtDisplay (w); + int screen_number = XScreenNumberOfScreen (XtScreen (w)); + double pixels = DisplayHeight (display, screen_number); + double mm = DisplayHeightMM (display, screen_number); + + return (fontsize * pixels * 25.4 / mm / 100); +} + + +int +main (int argc, char **argv) +{ + XtAppContext context; + Widget shell, form, quit, viewport, text; + String quit_action = "q: set() notify() unset()"; + XtActionsRec actions[] = { {"Expose", ExposeProc} }; + Arg arg[10]; + int i; + int viewport_width, viewport_height; + char *coding_name = NULL; + FILE *fp = stdin; + MSymbol coding; + int fontsize = 0; + + /* Open an application context. */ + XtSetLanguageProc (NULL, NULL, NULL); + shell = XtOpenApplication (&context, "M17NView", NULL, 0, &argc, argv, NULL, + sessionShellWidgetClass, NULL, 0); + XtAppAddActions (context, actions, XtNumber (actions)); + + /* Parse the remaining command line arguments. */ + for (i = 1; i < argc; i++) + { + if (! strcmp (argv[i], "--help") + || ! strcmp (argv[i], "-h")) + help_exit (argv[0], 0); + else if (! strcmp (argv[i], "--version")) + { + printf ("m17n-view (m17n library) %s\n", M17NLIB_VERSION_NAME); + printf ("Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 AIST, JAPAN\n"); + exit (0); + } + else if (! strcmp (argv[i], "-e")) + { + i++; + coding_name = argv[i]; + } + else if (! strcmp (argv[i], "-s")) + { + double n; + i++; + n = atof (argv[i]); + if (n <= 0) + FATAL_ERROR ("Invalid fontsize %s!\n", argv[i]); + fontsize = adjust_fontsize (shell, (int) (n * 10)); + } + else if (argv[i][0] != '-') + { + fp = fopen (argv[i], "r"); + if (! fp) + FATAL_ERROR ("Fail to open the file %s!\n", argv[i]); + } + else + { + printf ("Unknown option: %s", argv[i]); + help_exit (argv[0], 1); + } + } + + /* Initialize the m17n library. */ + M17N_INIT (); + if (merror_code != MERROR_NONE) + FATAL_ERROR ("%s\n", "Fail to initialize the m17n library."); + + /* Decide how to decode the input stream. */ + if (coding_name) + { + coding = mconv_resolve_coding (msymbol (coding_name)); + if (coding == Mnil) + FATAL_ERROR ("Invalid coding: %s\n", coding_name); + } + else + coding = Mcoding_utf_8; + + mt = mconv_decode_stream (coding, fp); + fclose (fp); + if (! mt) + FATAL_ERROR ("%s\n", "Fail to decode the input file or stream!"); + + { + MPlist *param = mplist (); + MFace *face = mface (); + + if (fontsize) + mface_put_prop (face, Msize, (void *) fontsize); + mplist_put (param, Mwidget, shell); + mplist_put (param, Mface, face); + frame = mframe (param); + m17n_object_unref (param); + m17n_object_unref (face); + } + + /* Create this widget hierarchy. + Shell - form -+- quit + | + +- viewport - text */ + + form = XtCreateManagedWidget ("form", formWidgetClass, shell, NULL, 0); + XtSetArg (arg[0], XtNleft, XawChainLeft); + XtSetArg (arg[1], XtNright, XawChainLeft); + XtSetArg (arg[2], XtNtop, XawChainTop); + XtSetArg (arg[3], XtNbottom, XawChainTop); + XtSetArg (arg[4], XtNaccelerators, XtParseAcceleratorTable (quit_action)); + quit = XtCreateManagedWidget ("quit", commandWidgetClass, form, arg, 5); + XtAddCallback (quit, XtNcallback, QuitProc, NULL); + + viewport_width = (int) mframe_get_prop (frame, Mfont_width) * 80; + viewport_height + = ((int) mframe_get_prop (frame, Mfont_ascent) + + (int) mframe_get_prop (frame, Mfont_descent)) * 24; + XtSetArg (arg[0], XtNallowVert, True); + XtSetArg (arg[1], XtNforceBars, False); + XtSetArg (arg[2], XtNfromVert, quit); + XtSetArg (arg[3], XtNtop, XawChainTop); + XtSetArg (arg[4], XtNbottom, XawChainBottom); + XtSetArg (arg[5], XtNright, XawChainRight); + XtSetArg (arg[6], XtNwidth, viewport_width); + XtSetArg (arg[7], XtNheight, viewport_height); + viewport = XtCreateManagedWidget ("viewport", viewportWidgetClass, form, + arg, 8); + + /* Before creating the text widget, we must calculate the height of + the M-text to draw. */ + control.two_dimensional = 1; + control.enable_bidi = 1; + control.disable_caching = 1; + control.max_line_width = viewport_width; + mdraw_text_extents (frame, mt, 0, mtext_len (mt), &control, + NULL, NULL, &metric); + + { + /* Decide the size of the text widget. */ + XtSetArg (arg[0], XtNwidth, viewport_width); + if (viewport_height > metric.height) + /* The outer viewport is tall enough. */ + XtSetArg (arg[1], XtNheight, viewport_height); + else if (metric.height < 0x8000) + /* The M-text height is within the limit of X. */ + XtSetArg (arg[1], XtNheight, metric.height); + else + /* We can't make such a tall widget. Truncate it. */ + XtSetArg (arg[1], XtNheight, 0x7FFF); + + /* We must provide our own expose event handler. */ + XtSetArg (arg[2], XtNtranslations, + XtParseTranslationTable ((String) ": Expose()")); + text = XtCreateManagedWidget ("text", simpleWidgetClass, viewport, arg, 3); + } + + /* Realize the top widget, and dive into an even loop. */ + XtInstallAllAccelerators (form, form); + XtRealizeWidget (shell); + XtAppMainLoop (context); + + /* Clear away. */ + m17n_object_unref (mt); + m17n_object_unref (frame); + M17N_FINI (); + + exit (0); +} + +#else /* not HAVE_X11_XAW_COMMAND_H */ + +int +main (int argc, char **argv) +{ + fprintf (stderr, + "Building of this program failed (lack of some header files)\n"); + exit (1); +} + +#endif /* not HAVE_X11_XAW_COMMAND_H */ + +#endif /* not FOR_DOXYGEN */ diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..59990a1 --- /dev/null +++ b/install-sh @@ -0,0 +1,508 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2014-09-12.12; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + # $RANDOM is not portable (e.g. dash); use it when possible to + # lower collision chance + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 + + # As "mkdir -p" follows symlinks and we work in /tmp possibly; so + # create the $tmpdir first (and fail if unsuccessful) to make sure + # that nobody tries to guess the $tmpdir name. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/intl/ChangeLog b/intl/ChangeLog new file mode 100755 index 0000000..3ec9081 --- /dev/null +++ b/intl/ChangeLog @@ -0,0 +1,4 @@ +2007-11-07 GNU + + * Version 0.17 released. + diff --git a/intl/Makefile.in b/intl/Makefile.in new file mode 100644 index 0000000..cfed085 --- /dev/null +++ b/intl/Makefile.in @@ -0,0 +1,587 @@ +# Makefile for directory with message catalog handling library of GNU gettext +# Copyright (C) 1995-1998, 2000-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. + +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 +WINDRES = @WINDRES@ + +# -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 \ + lock.c \ + relocatable.c \ + langprefs.c \ + localename.c \ + log.c \ + printf.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 \ + lock.$lo \ + relocatable.$lo \ + langprefs.$lo \ + localename.$lo \ + log.$lo \ + printf.$lo \ + version.$lo \ + osdep.$lo \ + intl-compat.$lo +OBJECTS_RES_yes = libintl.res +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) + rm -f $@ + $(AR) cru $@ $(OBJECTS) + $(RANLIB) $@ + +libintl.la libgnuintl.la: $(OBJECTS) $(OBJECTS_RES_@WOE32@) + $(LIBTOOL) --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=8 +LTV_REVISION=2 +LTV_AGE=0 + +.SUFFIXES: +.SUFFIXES: .c .y .o .lo .sin .sed + +.c.o: + $(COMPILE) $< + +.y.c: + $(YACC) $(YFLAGS) --output $@ $< + rm -f $*.h + +bindtextdom.lo: $(srcdir)/bindtextdom.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/bindtextdom.c +dcgettext.lo: $(srcdir)/dcgettext.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dcgettext.c +dgettext.lo: $(srcdir)/dgettext.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dgettext.c +gettext.lo: $(srcdir)/gettext.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/gettext.c +finddomain.lo: $(srcdir)/finddomain.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/finddomain.c +hash-string.lo: $(srcdir)/hash-string.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/hash-string.c +loadmsgcat.lo: $(srcdir)/loadmsgcat.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/loadmsgcat.c +localealias.lo: $(srcdir)/localealias.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localealias.c +textdomain.lo: $(srcdir)/textdomain.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/textdomain.c +l10nflist.lo: $(srcdir)/l10nflist.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/l10nflist.c +explodename.lo: $(srcdir)/explodename.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/explodename.c +dcigettext.lo: $(srcdir)/dcigettext.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dcigettext.c +dcngettext.lo: $(srcdir)/dcngettext.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dcngettext.c +dngettext.lo: $(srcdir)/dngettext.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/dngettext.c +ngettext.lo: $(srcdir)/ngettext.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/ngettext.c +plural.lo: $(srcdir)/plural.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/plural.c +plural-exp.lo: $(srcdir)/plural-exp.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/plural-exp.c +localcharset.lo: $(srcdir)/localcharset.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localcharset.c +lock.lo: $(srcdir)/lock.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/lock.c +relocatable.lo: $(srcdir)/relocatable.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/relocatable.c +langprefs.lo: $(srcdir)/langprefs.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/langprefs.c +localename.lo: $(srcdir)/localename.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localename.c +log.lo: $(srcdir)/log.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/log.c +printf.lo: $(srcdir)/printf.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/printf.c +version.lo: $(srcdir)/version.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/version.c +osdep.lo: $(srcdir)/osdep.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/osdep.c +intl-compat.lo: $(srcdir)/intl-compat.c + $(LIBTOOL) --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. We can use +# GNU bash's $'\n' syntax to obtain such a newline. +libintl.res: $(srcdir)/libintl.rc + nl=$$'\n'; \ + 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 --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_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_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 \ + test @GLIBC21@ != no || $(mkdir_p) $(DESTDIR)$(libdir); \ + 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 test @GLIBC21@ = no; 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 \ + test @GLIBC21@ != no || $(mkdir_p) $(DESTDIR)$(libdir); \ + $(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 textdomain.$lo: $(srcdir)/gettextP.h $(srcdir)/gmo.h $(srcdir)/loadinfo.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 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 libintl.res 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 0000000..889d4e9 --- /dev/null +++ b/intl/VERSION @@ -0,0 +1 @@ +GNU gettext library from gettext-0.17 diff --git a/intl/bindtextdom.c b/intl/bindtextdom.c new file mode 100644 index 0000000..dab5d4f --- /dev/null +++ b/intl/bindtextdom.c @@ -0,0 +1,340 @@ +/* Implementation of the bindtextdomain(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 +#endif + +#include +#include +#include + +#include "gettextP.h" +#ifdef _LIBC +# include +#else +# include "libgnuintl.h" +#endif + +/* Handle multi-threaded applications. */ +#ifdef _LIBC +# include +# 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 . */ +#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)) + { + if (binding->codeset != NULL) + 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 0000000..e8c258b --- /dev/null +++ b/intl/config.charset @@ -0,0 +1,640 @@ +#! /bin/sh +# Output a system dependent table of character encoding aliases. +# +# Copyright (C) 2000-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. +# +# 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 +# ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd darwin +# ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd darwin +# ISO-8859-3 Y glibc solaris +# ISO-8859-4 Y osf solaris freebsd netbsd darwin +# ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd netbsd darwin +# ISO-8859-6 Y glibc aix hpux solaris +# ISO-8859-7 Y glibc aix hpux irix osf solaris netbsd darwin +# ISO-8859-8 Y glibc aix hpux osf solaris +# ISO-8859-9 Y glibc aix hpux irix osf solaris darwin +# ISO-8859-13 glibc netbsd darwin +# ISO-8859-14 glibc +# ISO-8859-15 glibc aix osf solaris freebsd darwin +# KOI8-R Y glibc solaris freebsd netbsd darwin +# KOI8-U Y glibc freebsd netbsd darwin +# 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 darwin dos +# CP869 dos +# CP874 woe32 dos +# CP922 aix +# CP932 aix woe32 dos +# CP943 aix +# CP949 osf woe32 dos +# CP950 woe32 dos +# CP1046 aix +# CP1124 aix +# CP1125 dos +# CP1129 aix +# CP1250 woe32 +# CP1251 glibc solaris netbsd darwin 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 +# EUC-TW glibc aix hpux irix osf solaris netbsd +# BIG5 Y glibc aix hpux osf solaris freebsd netbsd darwin +# BIG5-HKSCS glibc solaris +# GBK glibc aix osf solaris woe32 dos +# GB18030 glibc solaris netbsd +# SHIFT_JIS Y hpux osf solaris freebsd netbsd darwin +# JOHAB glibc solaris woe32 +# TIS-620 glibc aix hpux osf solaris +# VISCII Y glibc +# TCVN5712-1 glibc +# GEORGIAN-PS 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 +# +# 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" + ;; + 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 it 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. + echo "* UTF-8" + ;; + beos*) + # BeOS has 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 " + echo "# and Bruno Haible ." + 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 0000000..c2a63f0 --- /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 +#endif + +#include "gettextP.h" +#ifdef _LIBC +# include +#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 0000000..623e51d --- /dev/null +++ b/intl/dcigettext.c @@ -0,0 +1,1689 @@ +/* Implementation of the internal dcigettext function. + Copyright (C) 1995-1999, 2000-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. */ + +/* Tell glibc's to provide a prototype for mempcpy(). + This must come before because may include + , and once has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* NL_LOCALE_NAME does not work in glibc-2.4. Ignore it. */ +#undef HAVE_NL_LOCALE_NAME + +#include + +#ifdef __GNUC__ +# define alloca __builtin_alloca +# define HAVE_ALLOCA 1 +#else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# if defined HAVE_ALLOCA_H || defined _LIBC +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +#include +#ifndef errno +extern int errno; +#endif +#ifndef __set_errno +# define __set_errno(val) errno = (val) +#endif + +#include +#include +#include + +#if defined HAVE_UNISTD_H || defined _LIBC +# include +#endif + +#include + +#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 +#endif + +#if defined HAVE_SYS_PARAM_H || defined _LIBC +# include +#endif + +#if !defined _LIBC +# if HAVE_NL_LOCALE_NAME +# include +# endif +# include "localcharset.h" +#endif + +#include "gettextP.h" +#include "plural-exp.h" +#ifdef _LIBC +# include +#else +# ifdef IN_LIBGLOCALE +# include +# endif +# include "libgnuintl.h" +#endif +#include "hash-string.h" + +/* Handle multi-threaded applications. */ +#ifdef _LIBC +# include +# 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 . */ +#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 +#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 +#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 +#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_NL_LOCALE_NAME || (HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS) || 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. */ + char msgid[ZERO]; +}; + +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->msgid, s2->msgid); + 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; + size_t msgid_len; +#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; + + 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 + + msgid_len = strlen (msgid1) + 1; + + /* Try to find the translation among those which we found at + some time. */ + search = (struct known_translation_t *) + alloca (offsetof (struct known_translation_t, msgid) + msgid_len); + memcpy (search->msgid, msgid1, msgid_len); + search->domainname = domainname; + search->category = category; +#ifdef HAVE_PER_THREAD_LOCALE +# ifndef IN_LIBGLOCALE +# ifdef _LIBC + localename = __current_locale_name (category); +# else +# if HAVE_NL_LOCALE_NAME + /* NL_LOCALE_NAME is public glibc API introduced in glibc-2.4. */ + localename = nl_langinfo (NL_LOCALE_NAME (category)); +# else +# if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS + /* The __names field is not public glibc API and must therefore not be used + in code that is installed in public locations. */ + { + locale_t thread_locale = uselocale (NULL); + if (thread_locale != LC_GLOBAL_LOCALE) + localename = thread_locale->__names[category]; + else + localename = ""; + } +# endif +# endif +# 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); + + freea (search); + 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); + __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. */ + categoryname = category_to_name (category); +#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 size; + struct known_translation_t *newp; + + 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, 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); + return retval; + } + } + } + + return_untranslated: + /* Return the untranslated MSGID. */ + FREE_BLOCKS (block_list); + gl_rwlock_unlock (_nl_state_lock); +#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); + + /* 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. */ + + if (convd->conv_tab == NULL + && ((convd->conv_tab = + (char **) calloc (nstrings + domain->n_sysdep_strings, + sizeof (char *))) + == NULL)) + /* Mark that we didn't succeed allocating a table. */ + convd->conv_tab = (char **) -1; + + 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. */ + __libc_lock_define_initialized (static, lock) +# 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 = NULL; +# endif + + __libc_lock_lock (lock); + + inbuf = (const unsigned char *) result; + outbuf = freemem + sizeof (size_t); + + 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 +# if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS + /* The __names field is not public glibc API and must therefore not be used + in code that is installed in public locations. */ + locale_t thread_locale = uselocale (NULL); + if (thread_locale != LC_GLOBAL_LOCALE) + { + locale = thread_locale->__names[category]; + locale_defaulted = 0; + } + else +# endif + { + locale = _nl_locale_name_posix (category, categoryname); + locale_defaulted = 0; + 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 0000000..eb36833 --- /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 +#endif + +#include "gettextP.h" +#ifdef _LIBC +# include +#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 0000000..9b0d0de --- /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 +#endif + +#include "gettextP.h" + +#include + +#ifdef _LIBC +# include +#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 0000000..3278438 --- /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 +#endif + +#include "gettextP.h" + +#include + +#ifdef _LIBC +# include +#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 0000000..21eecb3 --- /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 0000000..eb5dd75 --- /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 , 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 +#endif + +#include +#include +#include + +#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 0000000..b5c47ad --- /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 0000000..cab2c99 --- /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 , 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 +#endif + +#include +#include +#include +#include + +#if defined HAVE_UNISTD_H || defined _LIBC +# include +#endif + +#include "gettextP.h" +#ifdef _LIBC +# include +#else +# include "libgnuintl.h" +#endif + +/* Handle multi-threaded applications. */ +#ifdef _LIBC +# include +# 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 0000000..d82d439 --- /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 +#endif + +#ifdef _LIBC +# define __need_NULL +# include +#else +# include /* Just for NULL. */ +#endif + +#include "gettextP.h" +#ifdef _LIBC +# include +#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 0000000..5706fb5 --- /dev/null +++ b/intl/gettextP.h @@ -0,0 +1,297 @@ +/* Header describing internals of libintl library. + Copyright (C) 1995-1999, 2000-2007 Free Software Foundation, Inc. + Written by Ulrich Drepper , 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 /* Get size_t. */ + +#ifdef _LIBC +# include "../iconv/gconv_int.h" +#else +# if HAVE_ICONV +# include +# endif +#endif + +/* Handle multi-threaded applications. */ +#ifdef _LIBC +# include +# 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 +# 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 +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_posix _nl_locale_name_posix +extern const char *_nl_locale_name_posix (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 0000000..da9dbaa --- /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 + +/* @@ 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 ) 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 0000000..3c513f0 --- /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 +#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 0000000..98c07e4 --- /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 0000000..9b9ecbb --- /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 +#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 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 0000000..7176589 --- /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 , 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 0000000..365aeb7 --- /dev/null +++ b/intl/l10nflist.c @@ -0,0 +1,400 @@ +/* Copyright (C) 1995-1999, 2000-2006 Free Software Foundation, Inc. + Contributed by Ulrich Drepper , 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 to provide a prototype for stpcpy(). + This must come before because may include + , and once has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#if defined _LIBC || defined HAVE_ARGZ_H +# include +#endif +#include +#include +#include + +#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) +{ + int 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 0000000..59c8def --- /dev/null +++ b/intl/langprefs.c @@ -0,0 +1,130 @@ +/* Determine the user's language preferences. + Copyright (C) 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. */ + +/* Written by Bruno Haible . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#if HAVE_CFPREFERENCESCOPYAPPVALUE +# include +# include +# include +# include +# include +extern void _nl_locale_name_canonicalize (char *name); +#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 + + return NULL; +} diff --git a/intl/libgnuintl.h.in b/intl/libgnuintl.h.in new file mode 100644 index 0000000..c9da798 --- /dev/null +++ b/intl/libgnuintl.h.in @@ -0,0 +1,419 @@ +/* Message catalogs for internationalization. + Copyright (C) 1995-1997, 2000-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 _LIBINTL_H +#define _LIBINTL_H 1 + +#include + +/* 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, defines __LOCALE_H (or _LOCALE_H in Solaris 2.5) + then includes (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 0x001100 +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 __GNUC__ >= 2 && !(__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 __GNUC__ >= 3 && !(__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 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 +#include + +/* Get va_list. */ +#if __STDC__ || defined __cplusplus || defined _MSC_VER +# include +#else +# include +#endif + +#undef fprintf +#define fprintf libintl_fprintf +extern int fprintf (FILE *, const char *, ...); +#undef vfprintf +#define vfprintf libintl_vfprintf +extern int vfprintf (FILE *, const char *, va_list); + +#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 *, ...); +#undef vprintf +#define vprintf libintl_vprintf +extern int vprintf (const char *, va_list); + +#undef sprintf +#define sprintf libintl_sprintf +extern int sprintf (char *, const char *, ...); +#undef vsprintf +#define vsprintf libintl_vsprintf +extern int vsprintf (char *, const char *, va_list); + +#if @HAVE_SNPRINTF@ + +#undef snprintf +#define snprintf libintl_snprintf +extern int snprintf (char *, size_t, const char *, ...); +#undef vsnprintf +#define vsnprintf libintl_vsnprintf +extern int vsnprintf (char *, size_t, const char *, va_list); + +#endif + +#if @HAVE_ASPRINTF@ + +#undef asprintf +#define asprintf libintl_asprintf +extern int asprintf (char **, const char *, ...); +#undef vasprintf +#define vasprintf libintl_vasprintf +extern int vasprintf (char **, const char *, va_list); + +#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 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 0000000..f00f0b3 --- /dev/null +++ b/intl/libintl.rc @@ -0,0 +1,38 @@ +/* Resources for intl.dll */ + +#include + +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 and Windows 95/98/ME\0" + VALUE "FileVersion", PACKAGE_VERSION_STRING "\0" + VALUE "InternalName", "intl.dll\0" + VALUE "LegalCopyright", "Copyright (C) 1995-2007\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 0000000..a7a1970 --- /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 , 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 0000000..3432a8c --- /dev/null +++ b/intl/loadmsgcat.c @@ -0,0 +1,1336 @@ +/* Load needed message catalogs. + Copyright (C) 1995-1999, 2000-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. */ + +/* Tell glibc's to provide a prototype for mempcpy(). + This must come before because may include + , and once has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#ifdef __GNUC__ +# undef alloca +# define alloca __builtin_alloca +# define HAVE_ALLOCA 1 +#else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# if defined HAVE_ALLOCA_H || defined _LIBC +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +#include +#include + +#if defined HAVE_UNISTD_H || defined _LIBC +# include +#endif + +#ifdef _LIBC +# include +# include +#endif + +#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \ + || (defined _LIBC && defined _POSIX_MAPPED_FILES) +# include +# undef HAVE_MMAP +# define HAVE_MMAP 1 +#else +# undef HAVE_MMAP +#endif + +#if defined HAVE_STDINT_H_WITH_UINTMAX || defined _LIBC +# include +#endif +#if defined HAVE_INTTYPES_H || defined _LIBC +# include +#endif + +#include "gmo.h" +#include "gettextP.h" +#include "hash-string.h" +#include "plural-exp.h" + +#ifdef _LIBC +# include "../locale/localeinfo.h" +# include +#endif + +/* Handle multi-threaded applications. */ +#ifdef _LIBC +# include +#else +# include "lock.h" +#endif + +/* Provide fallback values for macros that ought to be defined in . + 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 . */ +#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. */ + if (domain->malloced) + 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); + } + if (domain->conversions != NULL) + free (domain->conversions); + __libc_rwlock_fini (domain->conversions_lock); + + if (domain->malloced) + 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 0000000..e796ae7 --- /dev/null +++ b/intl/localcharset.c @@ -0,0 +1,461 @@ +/* Determine a canonical name for the current locale's character encoding. + + Copyright (C) 2000-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. */ + +/* Written by Bruno Haible . */ + +#include + +/* Specification. */ +#include "localcharset.h" + +#include +#include +#include +#include + +#if defined _WIN32 || defined __WIN32__ +# define WIN32_NATIVE +#endif + +#if defined __EMX__ +/* Assume EMX program runs on OS/2, even if compiled under DOS. */ +# define OS2 +#endif + +#if !defined WIN32_NATIVE +# if HAVE_LANGINFO_CODESET +# include +# else +# if 0 /* see comment below */ +# include +# endif +# endif +# ifdef __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include +# endif +#elif defined WIN32_NATIVE +# define WIN32_LEAN_AND_MEAN +# include +#endif +#if defined OS2 +# define INCL_DOS +# include +#endif + +#if ENABLE_RELOCATABLE +# include "relocatable.h" +#else +# define relocate(pathname) (pathname) +#endif + +/* Get LIBDIR. */ +#ifndef LIBDIR +# include "configmake.h" +#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 VMS || defined WIN32_NATIVE || defined __CYGWIN__) + FILE *fp; + 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 || (fp = fopen (file_name, "r")) == NULL) + /* Out of memory or file not found, treat it as empty. */ + 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; + } + } + + if (file_name != NULL) + free (file_name); + +#else + +# 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 2006 does not have locales. nl_langinfo (CODESET) always + returns "US-ASCII". As long as this is not fixed, 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. */ + 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. */ + 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 0000000..129e4a4 --- /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 0000000..1044a40 --- /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 +bokm�l 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 +fran�ais 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 0000000..910db53 --- /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 to provide a prototype for mempcpy(). + This must come before because may include + , and once has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#if defined _LIBC || defined HAVE___FSETLOCKING +# include +#endif +#include + +#ifdef __GNUC__ +# undef alloca +# define alloca __builtin_alloca +# define HAVE_ALLOCA 1 +#else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# if defined HAVE_ALLOCA_H || defined _LIBC +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +#include +#include + +#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 +#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 0000000..af4c229 --- /dev/null +++ b/intl/localename.c @@ -0,0 +1,1507 @@ +/* Determine name of the currently selected locale. + Copyright (C) 1995-1999, 2000-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 Ulrich Drepper , 1995. */ +/* Win32 code written by Tor Lillqvist . */ +/* MacOS X code written by Bruno Haible . */ + +#include + +/* Specification. */ +#ifdef IN_LIBINTL +# include "gettextP.h" +#else +# include "localename.h" +#endif + +#include +#include + +#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE +# include +# include +# if HAVE_CFLOCALECOPYCURRENT +# include +# elif HAVE_CFPREFERENCESCOPYAPPVALUE +# include +# endif +#endif + +#if defined _WIN32 || defined __WIN32__ +# define WIN32_NATIVE +#endif + +#ifdef WIN32_NATIVE +# define WIN32_LEAN_AND_MEAN +# include +/* 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_RHAETO_ROMANCE + 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_SAAMI + 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 + 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 +*/ +/* 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_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_BASQUE +# define LANG_BASQUE 0x2d +# endif +# ifndef LANG_BELARUSIAN +# define LANG_BELARUSIAN 0x23 +# endif +# ifndef LANG_BENGALI +# define LANG_BENGALI 0x45 +# 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_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_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_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_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_MARATHI +# define LANG_MARATHI 0x4e +# endif +# ifndef LANG_MONGOLIAN +# define LANG_MONGOLIAN 0x50 +# endif +# ifndef LANG_NEPALI +# define LANG_NEPALI 0x61 +# 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_RHAETO_ROMANCE +# define LANG_RHAETO_ROMANCE 0x17 +# endif +# ifndef LANG_SAAMI +# define LANG_SAAMI 0x3b +# endif +# ifndef LANG_SANSKRIT +# define LANG_SANSKRIT 0x4f +# 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_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_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_XHOSA +# define LANG_XHOSA 0x34 +# 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_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_AZERI_LATIN +# define SUBLANG_AZERI_LATIN 0x01 +# endif +# ifndef SUBLANG_AZERI_CYRILLIC +# define SUBLANG_AZERI_CYRILLIC 0x02 +# endif +# ifndef SUBLANG_BENGALI_INDIA +# define SUBLANG_BENGALI_INDIA 0x01 +# endif +# ifndef SUBLANG_BENGALI_BANGLADESH +# define SUBLANG_BENGALI_BANGLADESH 0x02 +# endif +# ifndef SUBLANG_CHINESE_MACAU +# define SUBLANG_CHINESE_MACAU 0x05 +# 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_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_GERMAN_LUXEMBOURG +# define SUBLANG_GERMAN_LUXEMBOURG 0x04 +# endif +# ifndef SUBLANG_GERMAN_LIECHTENSTEIN +# define SUBLANG_GERMAN_LIECHTENSTEIN 0x05 +# endif +# ifndef SUBLANG_KASHMIRI_INDIA +# define SUBLANG_KASHMIRI_INDIA 0x02 +# 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_NEPALI_INDIA +# define SUBLANG_NEPALI_INDIA 0x02 +# endif +# ifndef SUBLANG_PUNJABI_INDIA +# define SUBLANG_PUNJABI_INDIA 0x01 +# endif +# ifndef SUBLANG_PUNJABI_PAKISTAN +# define SUBLANG_PUNJABI_PAKISTAN 0x02 +# endif +# ifndef SUBLANG_ROMANIAN_ROMANIA +# define SUBLANG_ROMANIAN_ROMANIA 0x01 +# endif +# ifndef SUBLANG_ROMANIAN_MOLDOVA +# define SUBLANG_ROMANIAN_MOLDOVA 0x02 +# endif +# ifndef SUBLANG_SERBIAN_LATIN +# define SUBLANG_SERBIAN_LATIN 0x02 +# endif +# ifndef SUBLANG_SERBIAN_CYRILLIC +# define SUBLANG_SERBIAN_CYRILLIC 0x03 +# endif +# ifndef SUBLANG_SINDHI_PAKISTAN +# define SUBLANG_SINDHI_PAKISTAN 0x01 +# endif +# ifndef SUBLANG_SINDHI_AFGHANISTAN +# define SUBLANG_SINDHI_AFGHANISTAN 0x02 +# 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_SWEDISH_FINLAND +# define SUBLANG_SWEDISH_FINLAND 0x02 +# 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_TIGRINYA_ETHIOPIA +# define SUBLANG_TIGRINYA_ETHIOPIA 0x01 +# endif +# ifndef SUBLANG_TIGRINYA_ERITREA +# define SUBLANG_TIGRINYA_ERITREA 0x02 +# 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 +#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 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 + +/* 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 + +/* 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_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 + 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') + return retval; + + return NULL; +#endif +} + +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. */ + +#if !(HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE || defined(WIN32_NATIVE)) + + /* 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) /* WIN32, not Cygwin */ + { + LCID lcid; + LANGID langid; + int primary, sub; + + /* Use native Win32 API locale ID. */ + lcid = GetThreadLocale (); + + /* Strip off the sorting rules, keep only the language part. */ + langid = LANGIDFROMLCID (lcid); + + /* 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: return "af_ZA"; + case LANG_ALBANIAN: return "sq_AL"; + case LANG_AMHARIC: return "am_ET"; + 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: return "hy_AM"; + case LANG_ASSAMESE: return "as_IN"; + case LANG_AZERI: + switch (sub) + { + /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */ + case SUBLANG_AZERI_LATIN: return "az_AZ@latin"; + case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic"; + } + return "az"; + case LANG_BASQUE: + switch (sub) + { + case SUBLANG_DEFAULT: return "eu_ES"; + } + return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */ + case LANG_BELARUSIAN: return "be_BY"; + case LANG_BENGALI: + switch (sub) + { + case SUBLANG_BENGALI_INDIA: return "bn_IN"; + case SUBLANG_BENGALI_BANGLADESH: return "bn_BD"; + } + return "bn"; + case LANG_BULGARIAN: return "bg_BG"; + case LANG_BURMESE: return "my_MM"; + case LANG_CAMBODIAN: return "km_KH"; + case LANG_CATALAN: return "ca_ES"; + case LANG_CHEROKEE: return "chr_US"; + case LANG_CHINESE: + switch (sub) + { + case SUBLANG_CHINESE_TRADITIONAL: return "zh_TW"; + case SUBLANG_CHINESE_SIMPLIFIED: return "zh_CN"; + case SUBLANG_CHINESE_HONGKONG: return "zh_HK"; + case SUBLANG_CHINESE_SINGAPORE: return "zh_SG"; + case SUBLANG_CHINESE_MACAU: return "zh_MO"; + } + return "zh"; + case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN + * 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) + { + case SUBLANG_DEFAULT: return "hr_HR"; + case SUBLANG_SERBIAN_LATIN: return "sr_CS"; + case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic"; + } + return "hr"; + case LANG_CZECH: return "cs_CZ"; + case LANG_DANISH: return "da_DK"; + case LANG_DIVEHI: return "dv_MV"; + case LANG_DUTCH: + switch (sub) + { + case SUBLANG_DUTCH: return "nl_NL"; + case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE"; + } + return "nl"; + case LANG_EDO: return "bin_NG"; + 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: return "et_EE"; + case LANG_FAEROESE: return "fo_FO"; + case LANG_FARSI: return "fa_IR"; + case LANG_FINNISH: return "fi_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: return "fy_NL"; + case LANG_FULFULDE: + /* Spoken in Nigeria, Guinea, Senegal, Mali, Niger, Cameroon, Benin. */ + return "ff_NG"; + case LANG_GAELIC: + switch (sub) + { + case 0x01: /* SCOTTISH */ return "gd_GB"; + case 0x02: /* IRISH */ return "ga_IE"; + } + return "C"; + case LANG_GALICIAN: return "gl_ES"; + case LANG_GEORGIAN: return "ka_GE"; + 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: return "el_GR"; + case LANG_GUARANI: return "gn_PY"; + case LANG_GUJARATI: return "gu_IN"; + case LANG_HAUSA: return "ha_NG"; + case LANG_HAWAIIAN: + /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers) + or Hawaii Creole English ("cpe_US", 600000 speakers)? */ + return "cpe_US"; + case LANG_HEBREW: return "he_IL"; + case LANG_HINDI: return "hi_IN"; + case LANG_HUNGARIAN: return "hu_HU"; + case LANG_IBIBIO: return "nic_NG"; + case LANG_ICELANDIC: return "is_IS"; + case LANG_IGBO: return "ig_NG"; + case LANG_INDONESIAN: return "id_ID"; + case LANG_INUKTITUT: return "iu_CA"; + case LANG_ITALIAN: + switch (sub) + { + case SUBLANG_ITALIAN: return "it_IT"; + case SUBLANG_ITALIAN_SWISS: return "it_CH"; + } + return "it"; + case LANG_JAPANESE: return "ja_JP"; + case LANG_KANNADA: return "kn_IN"; + case LANG_KANURI: return "kr_NG"; + case LANG_KASHMIRI: + switch (sub) + { + case SUBLANG_DEFAULT: return "ks_PK"; + case SUBLANG_KASHMIRI_INDIA: return "ks_IN"; + } + return "ks"; + case LANG_KAZAK: return "kk_KZ"; + case LANG_KONKANI: + /* FIXME: Adjust this when such locales appear on Unix. */ + return "kok_IN"; + case LANG_KOREAN: return "ko_KR"; + case LANG_KYRGYZ: return "ky_KG"; + case LANG_LAO: return "lo_LA"; + case LANG_LATIN: return "la_VA"; + case LANG_LATVIAN: return "lv_LV"; + case LANG_LITHUANIAN: return "lt_LT"; + case LANG_MACEDONIAN: return "mk_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: return "ml_IN"; + case LANG_MALTESE: return "mt_MT"; + case LANG_MANIPURI: + /* FIXME: Adjust this when such locales appear on Unix. */ + return "mni_IN"; + case LANG_MARATHI: return "mr_IN"; + case LANG_MONGOLIAN: + switch (sub) + { + case SUBLANG_DEFAULT: return "mn_MN"; + } + return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */ + case LANG_NEPALI: + switch (sub) + { + case SUBLANG_DEFAULT: return "ne_NP"; + case SUBLANG_NEPALI_INDIA: return "ne_IN"; + } + return "ne"; + case LANG_NORWEGIAN: + switch (sub) + { + case SUBLANG_NORWEGIAN_BOKMAL: return "nb_NO"; + case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO"; + } + return "no"; + case LANG_ORIYA: return "or_IN"; + case LANG_OROMO: return "om_ET"; + case LANG_PAPIAMENTU: return "pap_AN"; + case LANG_PASHTO: + return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */ + case LANG_POLISH: return "pl_PL"; + case LANG_PORTUGUESE: + switch (sub) + { + case SUBLANG_PORTUGUESE: return "pt_PT"; + /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT. + Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */ + case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR"; + } + 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_RHAETO_ROMANCE: return "rm_CH"; + case LANG_ROMANIAN: + switch (sub) + { + case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO"; + case SUBLANG_ROMANIAN_MOLDOVA: return "ro_MD"; + } + return "ro"; + case LANG_RUSSIAN: + switch (sub) + { + case SUBLANG_DEFAULT: return "ru_RU"; + } + return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */ + case LANG_SAAMI: /* actually Northern Sami */ return "se_NO"; + case LANG_SANSKRIT: return "sa_IN"; + case LANG_SINDHI: + switch (sub) + { + case SUBLANG_SINDHI_PAKISTAN: return "sd_PK"; + case SUBLANG_SINDHI_AFGHANISTAN: return "sd_AF"; + } + return "sd"; + case LANG_SINHALESE: return "si_LK"; + case LANG_SLOVAK: return "sk_SK"; + case LANG_SLOVENIAN: return "sl_SI"; + case LANG_SOMALI: return "so_SO"; + case LANG_SORBIAN: + /* FIXME: Adjust this when such locales appear on Unix. */ + return "wen_DE"; + 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"; + } + return "es"; + case LANG_SUTU: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */ + case LANG_SWAHILI: return "sw_KE"; + case LANG_SWEDISH: + switch (sub) + { + case SUBLANG_DEFAULT: return "sv_SE"; + case SUBLANG_SWEDISH_FINLAND: return "sv_FI"; + } + return "sv"; + case LANG_SYRIAC: return "syr_TR"; /* An extinct language. */ + case LANG_TAGALOG: return "tl_PH"; + case LANG_TAJIK: return "tg_TJ"; + case LANG_TAMAZIGHT: + switch (sub) + { + /* FIXME: Adjust this when Tamazight locales appear on Unix. */ + case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic"; + case SUBLANG_TAMAZIGHT_ALGERIA_LATIN: return "ber_DZ@latin"; + } + return "ber_MA"; + case LANG_TAMIL: + switch (sub) + { + case SUBLANG_DEFAULT: return "ta_IN"; + } + return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */ + case LANG_TATAR: return "tt_RU"; + case LANG_TELUGU: return "te_IN"; + case LANG_THAI: return "th_TH"; + case LANG_TIBETAN: return "bo_CN"; + case LANG_TIGRINYA: + switch (sub) + { + case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET"; + case SUBLANG_TIGRINYA_ERITREA: return "ti_ER"; + } + return "ti"; + case LANG_TSONGA: return "ts_ZA"; + case LANG_TSWANA: return "tn_BW"; + case LANG_TURKISH: return "tr_TR"; + case LANG_TURKMEN: return "tk_TM"; + case LANG_UKRAINIAN: return "uk_UA"; + 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 SUBLANG_UZBEK_LATIN: return "uz_UZ"; + case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic"; + } + return "uz"; + case LANG_VENDA: return "ve_ZA"; + case LANG_VIETNAMESE: return "vi_VN"; + case LANG_WELSH: return "cy_GB"; + case LANG_XHOSA: return "xh_ZA"; + case LANG_YI: return "sit_CN"; + case LANG_YIDDISH: return "yi_IL"; + case LANG_YORUBA: return "yo_NG"; + case LANG_ZULU: return "zu_ZA"; + default: return "C"; + } + } +# endif +#endif +} + +const char * +gl_locale_name (int category, const char *categoryname) +{ + const char *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 0000000..f60a8d9 --- /dev/null +++ b/intl/lock.c @@ -0,0 +1,922 @@ +/* Locking in multithreaded situations. + Copyright (C) 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. */ + +/* Written by Bruno Haible , 2005. + Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h, + gthr-win32.h. */ + +#include + +#include "lock.h" + +/* ========================================================================= */ + +#if USE_POSIX_THREADS + +/* Use the POSIX threads library. */ + +# 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 + +/* -------------------------- gl_lock_t datatype -------------------------- */ + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +# if HAVE_PTHREAD_RWLOCK + +# if !defined PTHREAD_RWLOCK_INITIALIZER + +void +glthread_rwlock_init (gl_rwlock_t *lock) +{ + if (pthread_rwlock_init (&lock->rwlock, NULL) != 0) + abort (); + lock->initialized = 1; +} + +void +glthread_rwlock_rdlock (gl_rwlock_t *lock) +{ + if (!lock->initialized) + { + if (pthread_mutex_lock (&lock->guard) != 0) + abort (); + if (!lock->initialized) + glthread_rwlock_init (lock); + if (pthread_mutex_unlock (&lock->guard) != 0) + abort (); + } + if (pthread_rwlock_rdlock (&lock->rwlock) != 0) + abort (); +} + +void +glthread_rwlock_wrlock (gl_rwlock_t *lock) +{ + if (!lock->initialized) + { + if (pthread_mutex_lock (&lock->guard) != 0) + abort (); + if (!lock->initialized) + glthread_rwlock_init (lock); + if (pthread_mutex_unlock (&lock->guard) != 0) + abort (); + } + if (pthread_rwlock_wrlock (&lock->rwlock) != 0) + abort (); +} + +void +glthread_rwlock_unlock (gl_rwlock_t *lock) +{ + if (!lock->initialized) + abort (); + if (pthread_rwlock_unlock (&lock->rwlock) != 0) + abort (); +} + +void +glthread_rwlock_destroy (gl_rwlock_t *lock) +{ + if (!lock->initialized) + abort (); + if (pthread_rwlock_destroy (&lock->rwlock) != 0) + abort (); + lock->initialized = 0; +} + +# endif + +# else + +void +glthread_rwlock_init (gl_rwlock_t *lock) +{ + if (pthread_mutex_init (&lock->lock, NULL) != 0) + abort (); + if (pthread_cond_init (&lock->waiting_readers, NULL) != 0) + abort (); + if (pthread_cond_init (&lock->waiting_writers, NULL) != 0) + abort (); + lock->waiting_writers_count = 0; + lock->runcount = 0; +} + +void +glthread_rwlock_rdlock (gl_rwlock_t *lock) +{ + if (pthread_mutex_lock (&lock->lock) != 0) + abort (); + /* 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. */ + if (pthread_cond_wait (&lock->waiting_readers, &lock->lock) != 0) + abort (); + } + lock->runcount++; + if (pthread_mutex_unlock (&lock->lock) != 0) + abort (); +} + +void +glthread_rwlock_wrlock (gl_rwlock_t *lock) +{ + if (pthread_mutex_lock (&lock->lock) != 0) + abort (); + /* 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++; + if (pthread_cond_wait (&lock->waiting_writers, &lock->lock) != 0) + abort (); + lock->waiting_writers_count--; + } + lock->runcount--; /* runcount becomes -1 */ + if (pthread_mutex_unlock (&lock->lock) != 0) + abort (); +} + +void +glthread_rwlock_unlock (gl_rwlock_t *lock) +{ + if (pthread_mutex_lock (&lock->lock) != 0) + abort (); + 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)) + abort (); + 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. */ + if (pthread_cond_signal (&lock->waiting_writers) != 0) + abort (); + } + else + { + /* Wake up all waiting readers. */ + if (pthread_cond_broadcast (&lock->waiting_readers) != 0) + abort (); + } + } + if (pthread_mutex_unlock (&lock->lock) != 0) + abort (); +} + +void +glthread_rwlock_destroy (gl_rwlock_t *lock) +{ + if (pthread_mutex_destroy (&lock->lock) != 0) + abort (); + if (pthread_cond_destroy (&lock->waiting_readers) != 0) + abort (); + if (pthread_cond_destroy (&lock->waiting_writers) != 0) + abort (); +} + +# endif + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +# if HAVE_PTHREAD_MUTEX_RECURSIVE + +# if !(defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) + +void +glthread_recursive_lock_init (gl_recursive_lock_t *lock) +{ + pthread_mutexattr_t attributes; + + if (pthread_mutexattr_init (&attributes) != 0) + abort (); + if (pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE) != 0) + abort (); + if (pthread_mutex_init (&lock->recmutex, &attributes) != 0) + abort (); + if (pthread_mutexattr_destroy (&attributes) != 0) + abort (); + lock->initialized = 1; +} + +void +glthread_recursive_lock_lock (gl_recursive_lock_t *lock) +{ + if (!lock->initialized) + { + if (pthread_mutex_lock (&lock->guard) != 0) + abort (); + if (!lock->initialized) + glthread_recursive_lock_init (lock); + if (pthread_mutex_unlock (&lock->guard) != 0) + abort (); + } + if (pthread_mutex_lock (&lock->recmutex) != 0) + abort (); +} + +void +glthread_recursive_lock_unlock (gl_recursive_lock_t *lock) +{ + if (!lock->initialized) + abort (); + if (pthread_mutex_unlock (&lock->recmutex) != 0) + abort (); +} + +void +glthread_recursive_lock_destroy (gl_recursive_lock_t *lock) +{ + if (!lock->initialized) + abort (); + if (pthread_mutex_destroy (&lock->recmutex) != 0) + abort (); + lock->initialized = 0; +} + +# endif + +# else + +void +glthread_recursive_lock_init (gl_recursive_lock_t *lock) +{ + if (pthread_mutex_init (&lock->mutex, NULL) != 0) + abort (); + lock->owner = (pthread_t) 0; + lock->depth = 0; +} + +void +glthread_recursive_lock_lock (gl_recursive_lock_t *lock) +{ + pthread_t self = pthread_self (); + if (lock->owner != self) + { + if (pthread_mutex_lock (&lock->mutex) != 0) + abort (); + lock->owner = self; + } + if (++(lock->depth) == 0) /* wraparound? */ + abort (); +} + +void +glthread_recursive_lock_unlock (gl_recursive_lock_t *lock) +{ + if (lock->owner != pthread_self ()) + abort (); + if (lock->depth == 0) + abort (); + if (--(lock->depth) == 0) + { + lock->owner = (pthread_t) 0; + if (pthread_mutex_unlock (&lock->mutex) != 0) + abort (); + } +} + +void +glthread_recursive_lock_destroy (gl_recursive_lock_t *lock) +{ + if (lock->owner != (pthread_t) 0) + abort (); + if (pthread_mutex_destroy (&lock->mutex) != 0) + abort (); +} + +# 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 -------------------------- */ + +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_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 --------------------- */ + +void +glthread_recursive_lock_init (gl_recursive_lock_t *lock) +{ + if (mutex_init (&lock->mutex, USYNC_THREAD, NULL) != 0) + abort (); + lock->owner = (thread_t) 0; + lock->depth = 0; +} + +void +glthread_recursive_lock_lock (gl_recursive_lock_t *lock) +{ + thread_t self = thr_self (); + if (lock->owner != self) + { + if (mutex_lock (&lock->mutex) != 0) + abort (); + lock->owner = self; + } + if (++(lock->depth) == 0) /* wraparound? */ + abort (); +} + +void +glthread_recursive_lock_unlock (gl_recursive_lock_t *lock) +{ + if (lock->owner != thr_self ()) + abort (); + if (lock->depth == 0) + abort (); + if (--(lock->depth) == 0) + { + lock->owner = (thread_t) 0; + if (mutex_unlock (&lock->mutex) != 0) + abort (); + } +} + +void +glthread_recursive_lock_destroy (gl_recursive_lock_t *lock) +{ + if (lock->owner != (thread_t) 0) + abort (); + if (mutex_destroy (&lock->mutex) != 0) + abort (); +} + +/* -------------------------- gl_once_t datatype -------------------------- */ + +void +glthread_once (gl_once_t *once_control, void (*initfunction) (void)) +{ + if (!once_control->inited) + { + /* Use the mutex to guarantee that if another thread is already calling + the initfunction, this thread waits until it's finished. */ + if (mutex_lock (&once_control->mutex) != 0) + abort (); + if (!once_control->inited) + { + once_control->inited = 1; + initfunction (); + } + if (mutex_unlock (&once_control->mutex) != 0) + abort (); + } +} + +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 (gl_lock_t *lock) +{ + InitializeCriticalSection (&lock->lock); + lock->guard.done = 1; +} + +void +glthread_lock_lock (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); +} + +void +glthread_lock_unlock (gl_lock_t *lock) +{ + if (!lock->guard.done) + abort (); + LeaveCriticalSection (&lock->lock); +} + +void +glthread_lock_destroy (gl_lock_t *lock) +{ + if (!lock->guard.done) + abort (); + DeleteCriticalSection (&lock->lock); + lock->guard.done = 0; +} + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +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; + } + 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 (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; +} + +void +glthread_rwlock_rdlock (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; + } + else + { + /* Allocation failure. Weird. */ + do + { + LeaveCriticalSection (&lock->lock); + Sleep (1); + EnterCriticalSection (&lock->lock); + } + while (!(lock->runcount + 1 > 0)); + } + } + lock->runcount++; + LeaveCriticalSection (&lock->lock); +} + +void +glthread_rwlock_wrlock (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; + } + 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); +} + +void +glthread_rwlock_unlock (gl_rwlock_t *lock) +{ + if (!lock->guard.done) + abort (); + 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)) + abort (); + 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); +} + +void +glthread_rwlock_destroy (gl_rwlock_t *lock) +{ + if (!lock->guard.done) + abort (); + if (lock->runcount != 0) + abort (); + 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; +} + +/* --------------------- gl_recursive_lock_t datatype --------------------- */ + +void +glthread_recursive_lock_init (gl_recursive_lock_t *lock) +{ + lock->owner = 0; + lock->depth = 0; + InitializeCriticalSection (&lock->lock); + lock->guard.done = 1; +} + +void +glthread_recursive_lock_lock (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? */ + abort (); + } +} + +void +glthread_recursive_lock_unlock (gl_recursive_lock_t *lock) +{ + if (lock->owner != GetCurrentThreadId ()) + abort (); + if (lock->depth == 0) + abort (); + if (--(lock->depth) == 0) + { + lock->owner = 0; + LeaveCriticalSection (&lock->lock); + } +} + +void +glthread_recursive_lock_destroy (gl_recursive_lock_t *lock) +{ + if (lock->owner != 0) + abort (); + DeleteCriticalSection (&lock->lock); + lock->guard.done = 0; +} + +/* -------------------------- gl_once_t datatype -------------------------- */ + +void +glthread_once (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 0000000..144531d --- /dev/null +++ b/intl/lock.h @@ -0,0 +1,1105 @@ +/* Locking in multithreaded situations. + Copyright (C) 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. */ + +/* Written by Bruno Haible , 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); + + 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); + + 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); + + Once-only execution: + Type: gl_once_t + Initializer: gl_once_define(extern, name) + Execution: gl_once (name, initfunction); +*/ + + +#ifndef _LOCK_H +#define _LOCK_H + +/* ========================================================================= */ + +#if USE_POSIX_THREADS + +/* Use the POSIX threads library. */ + +# include +# include + +# 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 gl_lock_init(NAME) \ + do \ + { \ + if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) \ + abort (); \ + } \ + while (0) +# define gl_lock_lock(NAME) \ + do \ + { \ + if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) \ + abort (); \ + } \ + while (0) +# define gl_lock_unlock(NAME) \ + do \ + { \ + if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) \ + abort (); \ + } \ + while (0) +# define gl_lock_destroy(NAME) \ + do \ + { \ + if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) \ + abort (); \ + } \ + while (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 gl_rwlock_init(NAME) \ + do \ + { \ + if (pthread_in_use () && pthread_rwlock_init (&NAME, NULL) != 0) \ + abort (); \ + } \ + while (0) +# define gl_rwlock_rdlock(NAME) \ + do \ + { \ + if (pthread_in_use () && pthread_rwlock_rdlock (&NAME) != 0) \ + abort (); \ + } \ + while (0) +# define gl_rwlock_wrlock(NAME) \ + do \ + { \ + if (pthread_in_use () && pthread_rwlock_wrlock (&NAME) != 0) \ + abort (); \ + } \ + while (0) +# define gl_rwlock_unlock(NAME) \ + do \ + { \ + if (pthread_in_use () && pthread_rwlock_unlock (&NAME) != 0) \ + abort (); \ + } \ + while (0) +# define gl_rwlock_destroy(NAME) \ + do \ + { \ + if (pthread_in_use () && pthread_rwlock_destroy (&NAME) != 0) \ + abort (); \ + } \ + while (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 gl_rwlock_init(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_rwlock_init (&NAME); \ + } \ + while (0) +# define gl_rwlock_rdlock(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_rwlock_rdlock (&NAME); \ + } \ + while (0) +# define gl_rwlock_wrlock(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_rwlock_wrlock (&NAME); \ + } \ + while (0) +# define gl_rwlock_unlock(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_rwlock_unlock (&NAME); \ + } \ + while (0) +# define gl_rwlock_destroy(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_rwlock_destroy (&NAME); \ + } \ + while (0) +extern void glthread_rwlock_init (gl_rwlock_t *lock); +extern void glthread_rwlock_rdlock (gl_rwlock_t *lock); +extern void glthread_rwlock_wrlock (gl_rwlock_t *lock); +extern void glthread_rwlock_unlock (gl_rwlock_t *lock); +extern void glthread_rwlock_destroy (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 gl_rwlock_init(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_rwlock_init (&NAME); \ + } \ + while (0) +# define gl_rwlock_rdlock(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_rwlock_rdlock (&NAME); \ + } \ + while (0) +# define gl_rwlock_wrlock(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_rwlock_wrlock (&NAME); \ + } \ + while (0) +# define gl_rwlock_unlock(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_rwlock_unlock (&NAME); \ + } \ + while (0) +# define gl_rwlock_destroy(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_rwlock_destroy (&NAME); \ + } \ + while (0) +extern void glthread_rwlock_init (gl_rwlock_t *lock); +extern void glthread_rwlock_rdlock (gl_rwlock_t *lock); +extern void glthread_rwlock_wrlock (gl_rwlock_t *lock); +extern void glthread_rwlock_unlock (gl_rwlock_t *lock); +extern void glthread_rwlock_destroy (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 gl_recursive_lock_init(NAME) \ + do \ + { \ + if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) \ + abort (); \ + } \ + while (0) +# define gl_recursive_lock_lock(NAME) \ + do \ + { \ + if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) \ + abort (); \ + } \ + while (0) +# define gl_recursive_lock_unlock(NAME) \ + do \ + { \ + if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) \ + abort (); \ + } \ + while (0) +# define gl_recursive_lock_destroy(NAME) \ + do \ + { \ + if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) \ + abort (); \ + } \ + while (0) + +# 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 gl_recursive_lock_init(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_recursive_lock_init (&NAME); \ + } \ + while (0) +# define gl_recursive_lock_lock(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_recursive_lock_lock (&NAME); \ + } \ + while (0) +# define gl_recursive_lock_unlock(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_recursive_lock_unlock (&NAME); \ + } \ + while (0) +# define gl_recursive_lock_destroy(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_recursive_lock_destroy (&NAME); \ + } \ + while (0) +extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock); +extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock); +extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock); +extern void glthread_recursive_lock_destroy (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 gl_recursive_lock_init(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_recursive_lock_init (&NAME); \ + } \ + while (0) +# define gl_recursive_lock_lock(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_recursive_lock_lock (&NAME); \ + } \ + while (0) +# define gl_recursive_lock_unlock(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_recursive_lock_unlock (&NAME); \ + } \ + while (0) +# define gl_recursive_lock_destroy(NAME) \ + do \ + { \ + if (pthread_in_use ()) \ + glthread_recursive_lock_destroy (&NAME); \ + } \ + while (0) +extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock); +extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock); +extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock); +extern void glthread_recursive_lock_destroy (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 gl_once(NAME, INITFUNCTION) \ + do \ + { \ + if (pthread_in_use ()) \ + { \ + if (pthread_once (&NAME, INITFUNCTION) != 0) \ + abort (); \ + } \ + else \ + { \ + if (glthread_once_singlethreaded (&NAME)) \ + INITFUNCTION (); \ + } \ + } \ + while (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 +# include + +# 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 gl_lock_init(NAME) \ + do \ + { \ + if (pth_in_use() && !pth_mutex_init (&NAME)) \ + abort (); \ + } \ + while (0) +# define gl_lock_lock(NAME) \ + do \ + { \ + if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) \ + abort (); \ + } \ + while (0) +# define gl_lock_unlock(NAME) \ + do \ + { \ + if (pth_in_use() && !pth_mutex_release (&NAME)) \ + abort (); \ + } \ + while (0) +# define gl_lock_destroy(NAME) \ + (void)(&NAME) + +/* ------------------------- 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 gl_rwlock_init(NAME) \ + do \ + { \ + if (pth_in_use() && !pth_rwlock_init (&NAME)) \ + abort (); \ + } \ + while (0) +# define gl_rwlock_rdlock(NAME) \ + do \ + { \ + if (pth_in_use() \ + && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) \ + abort (); \ + } \ + while (0) +# define gl_rwlock_wrlock(NAME) \ + do \ + { \ + if (pth_in_use() \ + && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) \ + abort (); \ + } \ + while (0) +# define gl_rwlock_unlock(NAME) \ + do \ + { \ + if (pth_in_use() && !pth_rwlock_release (&NAME)) \ + abort (); \ + } \ + while (0) +# define gl_rwlock_destroy(NAME) \ + (void)(&NAME) + +/* --------------------- 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 gl_recursive_lock_init(NAME) \ + do \ + { \ + if (pth_in_use() && !pth_mutex_init (&NAME)) \ + abort (); \ + } \ + while (0) +# define gl_recursive_lock_lock(NAME) \ + do \ + { \ + if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) \ + abort (); \ + } \ + while (0) +# define gl_recursive_lock_unlock(NAME) \ + do \ + { \ + if (pth_in_use() && !pth_mutex_release (&NAME)) \ + abort (); \ + } \ + while (0) +# define gl_recursive_lock_destroy(NAME) \ + (void)(&NAME) + +/* -------------------------- 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 gl_once(NAME, INITFUNCTION) \ + do \ + { \ + if (pth_in_use ()) \ + { \ + void (*gl_once_temp) (void) = INITFUNCTION; \ + if (!pth_once (&NAME, glthread_once_call, &gl_once_temp)) \ + abort (); \ + } \ + else \ + { \ + if (glthread_once_singlethreaded (&NAME)) \ + INITFUNCTION (); \ + } \ + } \ + while (0) +extern void glthread_once_call (void *arg); +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 +# include +# include + +# 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 gl_lock_init(NAME) \ + do \ + { \ + if (thread_in_use () && mutex_init (&NAME, USYNC_THREAD, NULL) != 0) \ + abort (); \ + } \ + while (0) +# define gl_lock_lock(NAME) \ + do \ + { \ + if (thread_in_use () && mutex_lock (&NAME) != 0) \ + abort (); \ + } \ + while (0) +# define gl_lock_unlock(NAME) \ + do \ + { \ + if (thread_in_use () && mutex_unlock (&NAME) != 0) \ + abort (); \ + } \ + while (0) +# define gl_lock_destroy(NAME) \ + do \ + { \ + if (thread_in_use () && mutex_destroy (&NAME) != 0) \ + abort (); \ + } \ + while (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 gl_rwlock_init(NAME) \ + do \ + { \ + if (thread_in_use () && rwlock_init (&NAME, USYNC_THREAD, NULL) != 0) \ + abort (); \ + } \ + while (0) +# define gl_rwlock_rdlock(NAME) \ + do \ + { \ + if (thread_in_use () && rw_rdlock (&NAME) != 0) \ + abort (); \ + } \ + while (0) +# define gl_rwlock_wrlock(NAME) \ + do \ + { \ + if (thread_in_use () && rw_wrlock (&NAME) != 0) \ + abort (); \ + } \ + while (0) +# define gl_rwlock_unlock(NAME) \ + do \ + { \ + if (thread_in_use () && rw_unlock (&NAME) != 0) \ + abort (); \ + } \ + while (0) +# define gl_rwlock_destroy(NAME) \ + do \ + { \ + if (thread_in_use () && rwlock_destroy (&NAME) != 0) \ + abort (); \ + } \ + while (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 gl_recursive_lock_init(NAME) \ + do \ + { \ + if (thread_in_use ()) \ + glthread_recursive_lock_init (&NAME); \ + } \ + while (0) +# define gl_recursive_lock_lock(NAME) \ + do \ + { \ + if (thread_in_use ()) \ + glthread_recursive_lock_lock (&NAME); \ + } \ + while (0) +# define gl_recursive_lock_unlock(NAME) \ + do \ + { \ + if (thread_in_use ()) \ + glthread_recursive_lock_unlock (&NAME); \ + } \ + while (0) +# define gl_recursive_lock_destroy(NAME) \ + do \ + { \ + if (thread_in_use ()) \ + glthread_recursive_lock_destroy (&NAME); \ + } \ + while (0) +extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock); +extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock); +extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock); +extern void glthread_recursive_lock_destroy (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 gl_once(NAME, INITFUNCTION) \ + do \ + { \ + if (thread_in_use ()) \ + { \ + glthread_once (&NAME, INITFUNCTION); \ + } \ + else \ + { \ + if (glthread_once_singlethreaded (&NAME)) \ + INITFUNCTION (); \ + } \ + } \ + while (0) +extern void glthread_once (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 + +# 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 gl_lock_init(NAME) \ + glthread_lock_init (&NAME) +# define gl_lock_lock(NAME) \ + glthread_lock_lock (&NAME) +# define gl_lock_unlock(NAME) \ + glthread_lock_unlock (&NAME) +# define gl_lock_destroy(NAME) \ + glthread_lock_destroy (&NAME) +extern void glthread_lock_init (gl_lock_t *lock); +extern void glthread_lock_lock (gl_lock_t *lock); +extern void glthread_lock_unlock (gl_lock_t *lock); +extern void glthread_lock_destroy (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_waitqueue_t; +typedef struct + { + gl_spinlock_t guard; /* protects the initialization */ + CRITICAL_SECTION lock; /* protects the remaining fields */ + gl_waitqueue_t waiting_readers; /* waiting readers */ + gl_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 gl_rwlock_init(NAME) \ + glthread_rwlock_init (&NAME) +# define gl_rwlock_rdlock(NAME) \ + glthread_rwlock_rdlock (&NAME) +# define gl_rwlock_wrlock(NAME) \ + glthread_rwlock_wrlock (&NAME) +# define gl_rwlock_unlock(NAME) \ + glthread_rwlock_unlock (&NAME) +# define gl_rwlock_destroy(NAME) \ + glthread_rwlock_destroy (&NAME) +extern void glthread_rwlock_init (gl_rwlock_t *lock); +extern void glthread_rwlock_rdlock (gl_rwlock_t *lock); +extern void glthread_rwlock_wrlock (gl_rwlock_t *lock); +extern void glthread_rwlock_unlock (gl_rwlock_t *lock); +extern void glthread_rwlock_destroy (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 gl_recursive_lock_init(NAME) \ + glthread_recursive_lock_init (&NAME) +# define gl_recursive_lock_lock(NAME) \ + glthread_recursive_lock_lock (&NAME) +# define gl_recursive_lock_unlock(NAME) \ + glthread_recursive_lock_unlock (&NAME) +# define gl_recursive_lock_destroy(NAME) \ + glthread_recursive_lock_destroy (&NAME) +extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock); +extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock); +extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock); +extern void glthread_recursive_lock_destroy (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 gl_once(NAME, INITFUNCTION) \ + glthread_once (&NAME, INITFUNCTION) +extern void glthread_once (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 gl_lock_init(NAME) +# define gl_lock_lock(NAME) +# define gl_lock_unlock(NAME) + +/* ------------------------- gl_rwlock_t datatype ------------------------- */ + +typedef int gl_rwlock_t; +# define gl_rwlock_define(STORAGECLASS, NAME) +# define gl_rwlock_define_initialized(STORAGECLASS, NAME) +# define gl_rwlock_init(NAME) +# define gl_rwlock_rdlock(NAME) +# define gl_rwlock_wrlock(NAME) +# define gl_rwlock_unlock(NAME) + +/* --------------------- 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 gl_recursive_lock_init(NAME) +# define gl_recursive_lock_lock(NAME) +# define gl_recursive_lock_unlock(NAME) + +/* -------------------------- gl_once_t datatype -------------------------- */ + +typedef int gl_once_t; +# define gl_once_define(STORAGECLASS, NAME) \ + STORAGECLASS gl_once_t NAME = 0; +# define gl_once(NAME, INITFUNCTION) \ + do \ + { \ + if (NAME == 0) \ + { \ + NAME = ~ 0; \ + INITFUNCTION (); \ + } \ + } \ + while (0) + +#endif + +/* ========================================================================= */ + +#endif /* _LOCK_H */ diff --git a/intl/log.c b/intl/log.c new file mode 100644 index 0000000..e3ab5d0 --- /dev/null +++ b/intl/log.c @@ -0,0 +1,116 @@ +/* Log file output. + Copyright (C) 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. */ + +/* Written by Bruno Haible . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +/* Handle multi-threaded applications. */ +#ifdef _LIBC +# include +#else +# include "lock.h" +#endif + +/* Print an ASCII string with quotes and escape sequences where needed. */ +static void +print_escaped (FILE *stream, const char *str) +{ + putc ('"', stream); + for (; *str != '\0'; str++) + if (*str == '\n') + { + fputs ("\\n\"", stream); + if (str[1] == '\0') + 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; + + /* 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); + fprintf (logfile, "\nmsgid "); + print_escaped (logfile, msgid1); + if (plural) + { + fprintf (logfile, "\nmsgid_plural "); + print_escaped (logfile, 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 0000000..a33529c --- /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 +#endif + +#ifdef _LIBC +# define __need_NULL +# include +#else +# include /* Just for NULL. */ +#endif + +#include "gettextP.h" +#ifdef _LIBC +# include +#else +# include "libgnuintl.h" +#endif + +#include + +/* @@ 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 0000000..d041de2 --- /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 +#endif + +#include +#include +#include + +/* 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 0000000..a18d582 --- /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 0000000..3cc35c0 --- /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 0000000..751a688 --- /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 , 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 +#endif + +#include +#include +#include + +#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 0000000..d6cb8c5 --- /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 , 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 0000000..7a4d947 --- /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 , 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 + because 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 +#endif + +#include +#include +#include +#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 /* 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 /* 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 /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* 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 /* 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 /* 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 /* 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 0000000..ec36a09 --- /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 , 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 + because 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 +#endif + +#include +#include +#include +#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 EQUOP2 CMPOP2 ADDOP2 MULOP2 +%token NUMBER +%type 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 0000000..cbd437d --- /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 +#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 0000000..cf89c3e --- /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 + +/* Get wchar_t. */ +#if HAVE_WCHAR_T +# include +#endif + +/* Get wint_t. */ +#if HAVE_WINT_T +# include +#endif + +/* Get va_list. */ +#include + + +/* 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 0000000..6ed1cc3 --- /dev/null +++ b/intl/printf-parse.c @@ -0,0 +1,590 @@ +/* Formatted output to strings. + Copyright (C) 1999-2000, 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. */ + +/* 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 +#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 + +/* Get intmax_t. */ +#if defined IN_LIBINTL || defined IN_LIBASPRINTF +# if HAVE_STDINT_H_WITH_UINTMAX +# include +# endif +# if HAVE_INTTYPES_H_WITH_UINTMAX +# include +# endif +#else +# include +#endif + +/* malloc(), realloc(), free(). */ +#include + +/* errno. */ +#include + +/* 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++; + } + 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 0000000..e785338 --- /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 0000000..0088e51 --- /dev/null +++ b/intl/printf.c @@ -0,0 +1,427 @@ +/* Formatted output to strings, using POSIX/XSI format strings with positions. + Copyright (C) 2003, 2006-2007 Free Software Foundation, Inc. + Written by Bruno Haible , 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 +#endif + +#ifdef __GNUC__ +# define alloca __builtin_alloca +# define HAVE_ALLOCA 1 +#else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# if defined HAVE_ALLOCA_H || defined _LIBC +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +#include + +#if !HAVE_POSIX_PRINTF + +#include +#include +#include +#include + +/* 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 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 + +#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 0000000..3678c28 --- /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 . +# +/^# 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 0000000..0c12d8e --- /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 . +# +/^# 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 0000000..5e1dde6 --- /dev/null +++ b/intl/relocatable.c @@ -0,0 +1,468 @@ +/* Provide relocatable packages. + Copyright (C) 2003-2006 Free Software Foundation, Inc. + Written by Bruno Haible , 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 to provide a prototype for getline(). + This must come before because may include + , and once has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#include + +/* Specification. */ +#include "relocatable.h" + +#if ENABLE_RELOCATABLE + +#include +#include +#include +#include + +#ifdef NO_XMALLOC +# define xmalloc malloc +#else +# include "xalloc.h" +#endif + +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include +#endif + +#if DEPENDS_ON_LIBCHARSET +# include +#endif +#if DEPENDS_ON_LIBICONV && HAVE_ICONV +# include +#endif +#if DEPENDS_ON_LIBINTL && ENABLE_NLS +# include +#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 NULL upon failure. */ +#ifdef IN_LIBRARY +#define compute_curr_prefix local_compute_curr_prefix +static +#endif +const char * +compute_curr_prefix (const char *orig_installprefix, + const char *orig_installdir, + const char *curr_pathname) +{ + const 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 filesystem 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 filesystem */ + 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. */ + 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) + return NULL; +#endif + memcpy (curr_prefix, curr_installdir, curr_prefix_len); + curr_prefix[curr_prefix_len] = '\0'; + + 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. */ +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; + const char *curr_prefix_better; + + curr_prefix_better = + compute_curr_prefix (orig_installprefix, orig_installdir, + get_shared_library_fullname ()); + if (curr_prefix_better == NULL) + curr_prefix_better = curr_prefix; + + set_relocation_prefix (orig_installprefix, curr_prefix_better); + + initialized = 1; + } +#endif + + /* Note: It is not necessary to perform case insensitive comparison here, + even for DOS-like filesystems, 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. */ + return curr_prefix; + 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 0000000..f6d3832 --- /dev/null +++ b/intl/relocatable.h @@ -0,0 +1,79 @@ +/* Provide relocatable packages. + Copyright (C) 2003, 2005 Free Software Foundation, Inc. + Written by Bruno Haible , 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. */ +extern const char * relocate (const char *pathname); + +/* Memory management: relocate() leaks 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. */ + +/* 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 NULL upon failure. */ +extern const 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/textdomain.c b/intl/textdomain.c new file mode 100644 index 0000000..70131bc --- /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 +#endif + +#include +#include + +#include "gettextP.h" +#ifdef _LIBC +# include +#else +# include "libgnuintl.h" +#endif + +/* Handle multi-threaded applications. */ +#ifdef _LIBC +# include +# 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/tsearch.c b/intl/tsearch.c new file mode 100644 index 0000000..d549dd4 --- /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 , 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 + +/* Specification. */ +#ifdef IN_LIBINTL +# include "tsearch.h" +#else +# include +#endif + +#include + +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 + +#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 0000000..f08e4a9 --- /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 + +#else + +#ifdef __cplusplus +extern "C" { +#endif + +/* See , + + 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 0000000..4a8e7f0 --- /dev/null +++ b/intl/vasnprintf.c @@ -0,0 +1,4677 @@ +/* vsprintf with automatic memory allocation. + Copyright (C) 1999, 2002-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: + 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 to provide a prototype for snprintf(). + This must come before because may include + , and once has been included, it's too late. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#ifndef VASNPRINTF +# include +#endif +#ifndef IN_LIBINTL +# include +#endif + +/* Specification. */ +#ifndef VASNPRINTF +# if WIDE_CHAR_VERSION +# include "vasnwprintf.h" +# else +# include "vasnprintf.h" +# endif +#endif + +#include /* localeconv() */ +#include /* snprintf(), sprintf() */ +#include /* abort(), malloc(), realloc(), free() */ +#include /* memcpy(), strlen() */ +#include /* errno */ +#include /* CHAR_BIT */ +#include /* DBL_MAX_EXP, LDBL_MAX_EXP */ +#if HAVE_NL_LANGINFO +# include +#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 +# include "float+.h" +#endif + +#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL +# include +# include "isnan.h" +#endif + +#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL +# include +# include "isnanl-nolibm.h" +# include "fpucw.h" +#endif + +#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL +# include +# include "isnan.h" +# include "printf-frexp.h" +#endif + +#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL +# include +# include "isnanl-nolibm.h" +# include "printf-frexpl.h" +# include "fpucw.h" +#endif + +/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ +#ifndef EOVERFLOW +# define EOVERFLOW E2BIG +#endif + +#if 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 + +/* 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 +# 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 +# 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 _snwprintf() function instead. */ +# define SNPRINTF _snwprintf +# 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. */ +# if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__ +# define USE_SNPRINTF 1 +# else +# define USE_SNPRINTF 0 +# endif +# if HAVE_DECL__SNPRINTF + /* Windows. */ +# define SNPRINTF _snprintf +# 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 + +#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_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 () +{ + const char *point; + /* Determine it in a multithread-safe way. We know nl_langinfo is + multithread-safe on glibc 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__ + 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 isnan (x) || x + x == x; +} + +#endif + +#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL + +/* Equivalent to !isfinite(x), but does not require libm. */ +static int +is_infinitel (long double x) +{ + return isnanl (x) || (x + x == x && x != 0.0L); +} + +#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=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=n>1, perform a multiple-precision division: + We have a/b < beta^(m-n+1). + s:=intDsize-1-(hightest bit in b[n-1]), 0<=s=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 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, 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 (!(y == 0.0L)) + abort (); + /* 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; + 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; + 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; + /* log(1-z) = - z - z^2/2 - z^3/3 - z^4/4 - ... + Four terms are enough to get an approximation with error < 10^-7. */ + l -= 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; + /* log(1-z) = - z - z^2/2 - z^3/3 - z^4/4 - ... + Four terms are enough to get an approximation with error < 10^-7. */ + l -= 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 + +#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. */ + if (u8_conv_to_encoding (locale_charset (), + iconveh_question_mark, + arg, arg_end - arg, NULL, + &converted, &converted_len) + < 0) +# else + /* Convert from UTF-8 to UTF-16/UTF-32. */ + converted = + U8_TO_DCHAR (arg, arg_end - arg, + converted, &converted_len); + if (converted == NULL) +# endif + { + 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. */ + if (u16_conv_to_encoding (locale_charset (), + iconveh_question_mark, + arg, arg_end - arg, NULL, + &converted, &converted_len) + < 0) +# else + /* Convert from UTF-16 to UTF-8/UTF-32. */ + converted = + U16_TO_DCHAR (arg, arg_end - arg, + converted, &converted_len); + if (converted == NULL) +# endif + { + 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. */ + if (u32_conv_to_encoding (locale_charset (), + iconveh_question_mark, + arg, arg_end - arg, NULL, + &converted, &converted_len) + < 0) +# else + /* Convert from UTF-32 to UTF-8/UTF-16. */ + converted = + U32_TO_DCHAR (arg, arg_end - arg, + converted, &converted_len); + if (converted == NULL) +# endif + { + 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 (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 (isnan (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. */ + && is_infinitel (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. */ + if (!has_precision) + 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 (!(isnan (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. */ + *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. */ + + /* 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. */ + 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 (isnan (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. */ + *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. */ + + /* 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 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION + int has_width; + size_t width; +#endif +#if !USE_SNPRINTF || 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 !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 !USE_SNPRINTF + size_t tmp_length; + TCHAR_T tmpbuf[700]; + TCHAR_T *tmp; +#endif + +#if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || 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 || 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 + +#if !USE_SNPRINTF + /* Allocate a temporary buffer of sufficient size for calling + sprintf. */ + { + switch (dp->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) + { + tmp_length = + local_wcslen (a.arg[dp->arg_index].a.a_wide_string); + +# if !WIDE_CHAR_VERSION + tmp_length = xtimes (tmp_length, MB_CUR_MAX); +# endif + } + else +# endif + tmp_length = strlen (a.arg[dp->arg_index].a.a_string); + 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 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 */ + } + + 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 + + /* 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 !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 + + /* 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)) + 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. */ + 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 (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)) + /* Prepare checking whether snprintf returns the count + via %n. */ + ENSURE_ALLOCATION (xsum (length, 1)); + *(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 + + 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) + { + /* 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. */ + size_t bigger_need = + xsum (xtimes (allocated, 2), 12); + ENSURE_ALLOCATION (bigger_need); + continue; + } + else + count = retcount; + } + } +#endif + + /* Attempt to handle failure. */ + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = 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 * sizeof (TCHAR_T) bytes. + But allocate proportionally, to avoid looping + eternally if snprintf() reports a too small + count. */ + size_t n = + xmax (xsum (length, + (count + 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 !DCHAR_IS_TCHAR +# if !USE_SNPRINTF + if (count >= tmp_length) + /* tmp_length was incorrectly calculated - fix the + code above! */ + abort (); +# endif + + /* 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 = NULL; + tmpdst_len = 0; + if (DCHAR_CONV_FROM_ENCODING (locale_charset (), + iconveh_question_mark, + tmpsrc, count, + NULL, + &tmpdst, &tmpdst_len) + < 0) + { + 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_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; +# if USE_SNPRINTF + /* 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)); + + length += count; + ENSURE_ALLOCATION (n); + length -= count; + } + /* Here count + pad <= allocated - length. */ +# endif + { +# 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; +# if NEED_PRINTF_FLAG_ZERO + DCHAR_T *pad_ptr; +# if !DCHAR_IS_TCHAR + 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; + } +# endif + /* 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++ = ' '; + } +# if NEED_PRINTF_FLAG_ZERO + 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'; + } +# endif + else + { + /* Pad with spaces on the left. */ + DCHAR_T *q = end; + + while (p > rp) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = ' '; + } + } + } + } +#endif + +#if DCHAR_IS_TCHAR && !USE_SNPRINTF + if (count >= tmp_length) + /* tmp_length was incorrectly calculated - fix the + code above! */ + abort (); +#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; + } + } + } + } + + /* 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; + + overflow: + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EOVERFLOW; + return NULL; + + 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 TCHARS_PER_DCHAR +#undef SNPRINTF +#undef USE_SNPRINTF +#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 0000000..ff1d183 --- /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 + +/* Get size_t. */ +#include + +#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 0000000..6ff03ce --- /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 + +/* Get wchar_t, size_t. */ +#include + +#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 0000000..a968cf7 --- /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 +#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 0000000..600b89a --- /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 0000000..b3023a7 --- /dev/null +++ b/intl/xsize.h @@ -0,0 +1,109 @@ +/* xsize.h -- Checked size_t computations. + + Copyright (C) 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 _XSIZE_H +#define _XSIZE_H + +/* Get size_t. */ +#include + +/* Get SIZE_MAX. */ +#include +#if HAVE_STDINT_H +# include +#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 tupe 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/ltmain.sh b/ltmain.sh new file mode 100644 index 0000000..147d758 --- /dev/null +++ b/ltmain.sh @@ -0,0 +1,11156 @@ +#! /bin/sh +## DO NOT EDIT - This file generated from ./build-aux/ltmain.in +## by inline-source v2014-01-03.01 + +# libtool (GNU libtool) 2.4.6 +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool 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 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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, see . + + +PROGRAM=libtool +PACKAGE=libtool +VERSION="2.4.6 Debian-2.4.6-0.1" +package_revision=2.4.6 + + +## ------ ## +## Usage. ## +## ------ ## + +# Run './libtool --help' for help with using this script from the +# command line. + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# After configure completes, it has a better idea of some of the +# shell tools we need than the defaults used by the functions shared +# with bootstrap, so set those here where they can still be over- +# ridden by the user, but otherwise take precedence. + +: ${AUTOCONF="autoconf"} +: ${AUTOMAKE="automake"} + + +## -------------------------- ## +## Source external libraries. ## +## -------------------------- ## + +# Much of our low-level functionality needs to be sourced from external +# libraries, which are installed to $pkgauxdir. + +# Set a version string for this script. +scriptversion=2015-01-20.17; # UTC + +# General shell script boiler plate, and helper functions. +# Written by Gary V. Vaughan, 2004 + +# Copyright (C) 2004-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# 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 3 of the License, or +# (at your option) any later version. + +# As a special exception to the GNU General Public License, if you distribute +# this file as part of a program or library that is built using GNU Libtool, +# you may include this file under the same distribution terms that you use +# for the rest of that program. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNES 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, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# Evaluate this file near the top of your script to gain access to +# the functions and variables defined here: +# +# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh +# +# If you need to override any of the default environment variable +# settings, do that before evaluating this file. + + +## -------------------- ## +## Shell normalisation. ## +## -------------------- ## + +# Some shells need a little help to be as Bourne compatible as possible. +# Before doing anything else, make sure all that help has been provided! + +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac +fi + +# NLS nuisances: We save the old values in case they are required later. +_G_user_locale= +_G_safe_locale= +for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test set = \"\${$_G_var+set}\"; then + save_$_G_var=\$$_G_var + $_G_var=C + export $_G_var + _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" + _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" + fi" +done + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Make sure IFS has a sensible default +sp=' ' +nl=' +' +IFS="$sp $nl" + +# There are apparently some retarded systems that use ';' as a PATH separator! +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + + +## ------------------------- ## +## Locate command utilities. ## +## ------------------------- ## + + +# func_executable_p FILE +# ---------------------- +# Check that FILE is an executable regular file. +func_executable_p () +{ + test -f "$1" && test -x "$1" +} + + +# func_path_progs PROGS_LIST CHECK_FUNC [PATH] +# -------------------------------------------- +# Search for either a program that responds to --version with output +# containing "GNU", or else returned by CHECK_FUNC otherwise, by +# trying all the directories in PATH with each of the elements of +# PROGS_LIST. +# +# CHECK_FUNC should accept the path to a candidate program, and +# set $func_check_prog_result if it truncates its output less than +# $_G_path_prog_max characters. +func_path_progs () +{ + _G_progs_list=$1 + _G_check_func=$2 + _G_PATH=${3-"$PATH"} + + _G_path_prog_max=0 + _G_path_prog_found=false + _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} + for _G_dir in $_G_PATH; do + IFS=$_G_save_IFS + test -z "$_G_dir" && _G_dir=. + for _G_prog_name in $_G_progs_list; do + for _exeext in '' .EXE; do + _G_path_prog=$_G_dir/$_G_prog_name$_exeext + func_executable_p "$_G_path_prog" || continue + case `"$_G_path_prog" --version 2>&1` in + *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; + *) $_G_check_func $_G_path_prog + func_path_progs_result=$func_check_prog_result + ;; + esac + $_G_path_prog_found && break 3 + done + done + done + IFS=$_G_save_IFS + test -z "$func_path_progs_result" && { + echo "no acceptable sed could be found in \$PATH" >&2 + exit 1 + } +} + + +# We want to be able to use the functions in this file before configure +# has figured out where the best binaries are kept, which means we have +# to search for them ourselves - except when the results are already set +# where we skip the searches. + +# Unless the user overrides by setting SED, search the path for either GNU +# sed, or the sed that truncates its output the least. +test -z "$SED" && { + _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for _G_i in 1 2 3 4 5 6 7; do + _G_sed_script=$_G_sed_script$nl$_G_sed_script + done + echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed + _G_sed_script= + + func_check_prog_sed () + { + _G_path_prog=$1 + + _G_count=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo '' >> conftest.nl + "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin + rm -f conftest.sed + SED=$func_path_progs_result +} + + +# Unless the user overrides by setting GREP, search the path for either GNU +# grep, or the grep that truncates its output the least. +test -z "$GREP" && { + func_check_prog_grep () + { + _G_path_prog=$1 + + _G_count=0 + _G_path_prog_max=0 + printf 0123456789 >conftest.in + while : + do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo 'GREP' >> conftest.nl + "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break + diff conftest.out conftest.nl >/dev/null 2>&1 || break + _G_count=`expr $_G_count + 1` + if test "$_G_count" -gt "$_G_path_prog_max"; then + # Best one so far, save it but keep looking for a better one + func_check_prog_result=$_G_path_prog + _G_path_prog_max=$_G_count + fi + # 10*(2^10) chars as input seems more than enough + test 10 -lt "$_G_count" && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out + } + + func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin + GREP=$func_path_progs_result +} + + +## ------------------------------- ## +## User overridable command paths. ## +## ------------------------------- ## + +# All uppercase variable names are used for environment variables. These +# variables can be overridden by the user before calling a script that +# uses them if a suitable command of that name is not already available +# in the command search PATH. + +: ${CP="cp -f"} +: ${ECHO="printf %s\n"} +: ${EGREP="$GREP -E"} +: ${FGREP="$GREP -F"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} + + +## -------------------- ## +## Useful sed snippets. ## +## -------------------- ## + +sed_dirname='s|/[^/]*$||' +sed_basename='s|^.*/||' + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s|\([`"$\\]\)|\\\1|g' + +# Same as above, but do not quote variable references. +sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' + +# Sed substitution that converts a w32 file name or path +# that contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-'\' parameter expansions in output of sed_double_quote_subst that +# were '\'-ed in input to the same. If an odd number of '\' preceded a +# '$' in input to sed_double_quote_subst, that '$' was protected from +# expansion. Since each input '\' is now two '\'s, look for any number +# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. +_G_bs='\\' +_G_bs2='\\\\' +_G_bs4='\\\\\\\\' +_G_dollar='\$' +sed_double_backslash="\ + s/$_G_bs4/&\\ +/g + s/^$_G_bs2$_G_dollar/$_G_bs&/ + s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g + s/\n//g" + + +## ----------------- ## +## Global variables. ## +## ----------------- ## + +# Except for the global variables explicitly listed below, the following +# functions in the '^func_' namespace, and the '^require_' namespace +# variables initialised in the 'Resource management' section, sourcing +# this file will not pollute your global namespace with anything +# else. There's no portable way to scope variables in Bourne shell +# though, so actually running these functions will sometimes place +# results into a variable named after the function, and often use +# temporary variables in the '^_G_' namespace. If you are careful to +# avoid using those namespaces casually in your sourcing script, things +# should continue to work as you expect. And, of course, you can freely +# overwrite any of the functions or variables defined here before +# calling anything to customize them. + +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +# Allow overriding, eg assuming that you follow the convention of +# putting '$debug_cmd' at the start of all your functions, you can get +# bash to show function call trace with: +# +# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name +debug_cmd=${debug_cmd-":"} +exit_cmd=: + +# By convention, finish your script with: +# +# exit $exit_status +# +# so that you can set exit_status to non-zero if you want to indicate +# something went wrong during execution without actually bailing out at +# the point of failure. +exit_status=$EXIT_SUCCESS + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath=$0 + +# The name of this program. +progname=`$ECHO "$progpath" |$SED "$sed_basename"` + +# Make sure we have an absolute progpath for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` + progdir=`cd "$progdir" && pwd` + progpath=$progdir/$progname + ;; + *) + _G_IFS=$IFS + IFS=${PATH_SEPARATOR-:} + for progdir in $PATH; do + IFS=$_G_IFS + test -x "$progdir/$progname" && break + done + IFS=$_G_IFS + test -n "$progdir" || progdir=`pwd` + progpath=$progdir/$progname + ;; +esac + + +## ----------------- ## +## Standard options. ## +## ----------------- ## + +# The following options affect the operation of the functions defined +# below, and should be set appropriately depending on run-time para- +# meters passed on the command line. + +opt_dry_run=false +opt_quiet=false +opt_verbose=false + +# Categories 'all' and 'none' are always available. Append any others +# you will pass as the first argument to func_warning from your own +# code. +warning_categories= + +# By default, display warnings according to 'opt_warning_types'. Set +# 'warning_func' to ':' to elide all warnings, or func_fatal_error to +# treat the next displayed warning as a fatal error. +warning_func=func_warn_and_continue + +# Set to 'all' to display all warnings, 'none' to suppress all +# warnings, or a space delimited list of some subset of +# 'warning_categories' to display only the listed warnings. +opt_warning_types=all + + +## -------------------- ## +## Resource management. ## +## -------------------- ## + +# This section contains definitions for functions that each ensure a +# particular resource (a file, or a non-empty configuration variable for +# example) is available, and if appropriate to extract default values +# from pertinent package files. Call them using their associated +# 'require_*' variable to ensure that they are executed, at most, once. +# +# It's entirely deliberate that calling these functions can set +# variables that don't obey the namespace limitations obeyed by the rest +# of this file, in order that that they be as useful as possible to +# callers. + + +# require_term_colors +# ------------------- +# Allow display of bold text on terminals that support it. +require_term_colors=func_require_term_colors +func_require_term_colors () +{ + $debug_cmd + + test -t 1 && { + # COLORTERM and USE_ANSI_COLORS environment variables take + # precedence, because most terminfo databases neglect to describe + # whether color sequences are supported. + test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} + + if test 1 = "$USE_ANSI_COLORS"; then + # Standard ANSI escape sequences + tc_reset='' + tc_bold=''; tc_standout='' + tc_red=''; tc_green='' + tc_blue=''; tc_cyan='' + else + # Otherwise trust the terminfo database after all. + test -n "`tput sgr0 2>/dev/null`" && { + tc_reset=`tput sgr0` + test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` + tc_standout=$tc_bold + test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` + test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` + test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` + test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` + test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` + } + fi + } + + require_term_colors=: +} + + +## ----------------- ## +## Function library. ## +## ----------------- ## + +# This section contains a variety of useful functions to call in your +# scripts. Take note of the portable wrappers for features provided by +# some modern shells, which will fall back to slower equivalents on +# less featureful shells. + + +# func_append VAR VALUE +# --------------------- +# Append VALUE onto the existing contents of VAR. + + # We should try to minimise forks, especially on Windows where they are + # unreasonably slow, so skip the feature probes when bash or zsh are + # being used: + if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then + : ${_G_HAVE_ARITH_OP="yes"} + : ${_G_HAVE_XSI_OPS="yes"} + # The += operator was introduced in bash 3.1 + case $BASH_VERSION in + [12].* | 3.0 | 3.0*) ;; + *) + : ${_G_HAVE_PLUSEQ_OP="yes"} + ;; + esac + fi + + # _G_HAVE_PLUSEQ_OP + # Can be empty, in which case the shell is probed, "yes" if += is + # useable or anything else if it does not work. + test -z "$_G_HAVE_PLUSEQ_OP" \ + && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ + && _G_HAVE_PLUSEQ_OP=yes + +if test yes = "$_G_HAVE_PLUSEQ_OP" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_append () + { + $debug_cmd + + eval "$1+=\$2" + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_append () + { + $debug_cmd + + eval "$1=\$$1\$2" + } +fi + + +# func_append_quoted VAR VALUE +# ---------------------------- +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +if test yes = "$_G_HAVE_PLUSEQ_OP"; then + eval 'func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1+=\\ \$func_quote_for_eval_result" + }' +else + func_append_quoted () + { + $debug_cmd + + func_quote_for_eval "$2" + eval "$1=\$$1\\ \$func_quote_for_eval_result" + } +fi + + +# func_append_uniq VAR VALUE +# -------------------------- +# Append unique VALUE onto the existing contents of VAR, assuming +# entries are delimited by the first character of VALUE. For example: +# +# func_append_uniq options " --another-option option-argument" +# +# will only append to $options if " --another-option option-argument " +# is not already present somewhere in $options already (note spaces at +# each end implied by leading space in second argument). +func_append_uniq () +{ + $debug_cmd + + eval _G_current_value='`$ECHO $'$1'`' + _G_delim=`expr "$2" : '\(.\)'` + + case $_G_delim$_G_current_value$_G_delim in + *"$2$_G_delim"*) ;; + *) func_append "$@" ;; + esac +} + + +# func_arith TERM... +# ------------------ +# Set func_arith_result to the result of evaluating TERMs. + test -z "$_G_HAVE_ARITH_OP" \ + && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ + && _G_HAVE_ARITH_OP=yes + +if test yes = "$_G_HAVE_ARITH_OP"; then + eval 'func_arith () + { + $debug_cmd + + func_arith_result=$(( $* )) + }' +else + func_arith () + { + $debug_cmd + + func_arith_result=`expr "$@"` + } +fi + + +# func_basename FILE +# ------------------ +# Set func_basename_result to FILE with everything up to and including +# the last / stripped. +if test yes = "$_G_HAVE_XSI_OPS"; then + # If this shell supports suffix pattern removal, then use it to avoid + # forking. Hide the definitions single quotes in case the shell chokes + # on unsupported syntax... + _b='func_basename_result=${1##*/}' + _d='case $1 in + */*) func_dirname_result=${1%/*}$2 ;; + * ) func_dirname_result=$3 ;; + esac' + +else + # ...otherwise fall back to using sed. + _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' + _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` + if test "X$func_dirname_result" = "X$1"; then + func_dirname_result=$3 + else + func_append func_dirname_result "$2" + fi' +fi + +eval 'func_basename () +{ + $debug_cmd + + '"$_b"' +}' + + +# func_dirname FILE APPEND NONDIR_REPLACEMENT +# ------------------------------------------- +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +eval 'func_dirname () +{ + $debug_cmd + + '"$_d"' +}' + + +# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT +# -------------------------------------------------------- +# Perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# For efficiency, we do not delegate to the functions above but instead +# duplicate the functionality here. +eval 'func_dirname_and_basename () +{ + $debug_cmd + + '"$_b"' + '"$_d"' +}' + + +# func_echo ARG... +# ---------------- +# Echo program name prefixed message. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_echo_all ARG... +# -------------------- +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + + +# func_echo_infix_1 INFIX ARG... +# ------------------------------ +# Echo program name, followed by INFIX on the first line, with any +# additional lines not showing INFIX. +func_echo_infix_1 () +{ + $debug_cmd + + $require_term_colors + + _G_infix=$1; shift + _G_indent=$_G_infix + _G_prefix="$progname: $_G_infix: " + _G_message=$* + + # Strip color escape sequences before counting printable length + for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" + do + test -n "$_G_tc" && { + _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` + _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` + } + done + _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes + + func_echo_infix_1_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_infix_1_IFS + $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 + _G_prefix=$_G_indent + done + IFS=$func_echo_infix_1_IFS +} + + +# func_error ARG... +# ----------------- +# Echo program name prefixed message to standard error. +func_error () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 +} + + +# func_fatal_error ARG... +# ----------------------- +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + $debug_cmd + + func_error "$*" + exit $EXIT_FAILURE +} + + +# func_grep EXPRESSION FILENAME +# ----------------------------- +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $debug_cmd + + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_len STRING +# --------------- +# Set func_len_result to the length of STRING. STRING may not +# start with a hyphen. + test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_len () + { + $debug_cmd + + func_len_result=${#1} + }' +else + func_len () + { + $debug_cmd + + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` + } +fi + + +# func_mkdir_p DIRECTORY-PATH +# --------------------------- +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + $debug_cmd + + _G_directory_path=$1 + _G_dir_list= + + if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then + + # Protect directory names starting with '-' + case $_G_directory_path in + -*) _G_directory_path=./$_G_directory_path ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$_G_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + _G_dir_list=$_G_directory_path:$_G_dir_list + + # If the last portion added has no slash in it, the list is done + case $_G_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` + done + _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` + + func_mkdir_p_IFS=$IFS; IFS=: + for _G_dir in $_G_dir_list; do + IFS=$func_mkdir_p_IFS + # mkdir can fail with a 'File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$_G_dir" 2>/dev/null || : + done + IFS=$func_mkdir_p_IFS + + # Bail out if we (or some other process) failed to create a directory. + test -d "$_G_directory_path" || \ + func_fatal_error "Failed to create '$1'" + fi +} + + +# func_mktempdir [BASENAME] +# ------------------------- +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, BASENAME is the basename for that directory. +func_mktempdir () +{ + $debug_cmd + + _G_template=${TMPDIR-/tmp}/${1-$progname} + + if test : = "$opt_dry_run"; then + # Return a directory name, but don't create it in dry-run mode + _G_tmpdir=$_G_template-$$ + else + + # If mktemp works, use that first and foremost + _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` + + if test ! -d "$_G_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + _G_tmpdir=$_G_template-${RANDOM-0}$$ + + func_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$_G_tmpdir" + umask $func_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$_G_tmpdir" || \ + func_fatal_error "cannot create temporary directory '$_G_tmpdir'" + fi + + $ECHO "$_G_tmpdir" +} + + +# func_normal_abspath PATH +# ------------------------ +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +func_normal_abspath () +{ + $debug_cmd + + # These SED scripts presuppose an absolute path with a trailing slash. + _G_pathcar='s|^/\([^/]*\).*$|\1|' + _G_pathcdr='s|^/[^/]*||' + _G_removedotparts=':dotsl + s|/\./|/|g + t dotsl + s|/\.$|/|' + _G_collapseslashes='s|/\{1,\}|/|g' + _G_finalslash='s|/*$|/|' + + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` + while :; do + # Processed it all yet? + if test / = "$func_normal_abspath_tpath"; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result"; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$_G_pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + + +# func_notquiet ARG... +# -------------------- +# Echo program name prefixed message only when not in quiet mode. +func_notquiet () +{ + $debug_cmd + + $opt_quiet || func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + + +# func_relative_path SRCDIR DSTDIR +# -------------------------------- +# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. +func_relative_path () +{ + $debug_cmd + + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=$func_dirname_result + if test -z "$func_relative_path_tlibdir"; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test -n "$func_stripname_result"; then + func_append func_relative_path_result "/$func_stripname_result" + fi + + # Normalisation. If bindir is libdir, return '.' else relative path. + if test -n "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + fi + + test -n "$func_relative_path_result" || func_relative_path_result=. + + : +} + + +# func_quote_for_eval ARG... +# -------------------------- +# Aesthetically quote ARGs to be evaled later. +# This function returns two values: +# i) func_quote_for_eval_result +# double-quoted, suitable for a subsequent eval +# ii) func_quote_for_eval_unquoted_result +# has all characters that are still active within double +# quotes backslashified. +func_quote_for_eval () +{ + $debug_cmd + + func_quote_for_eval_unquoted_result= + func_quote_for_eval_result= + while test 0 -lt $#; do + case $1 in + *[\\\`\"\$]*) + _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; + *) + _G_unquoted_arg=$1 ;; + esac + if test -n "$func_quote_for_eval_unquoted_result"; then + func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" + else + func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" + fi + + case $_G_unquoted_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and variable expansion + # for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_quoted_arg=\"$_G_unquoted_arg\" + ;; + *) + _G_quoted_arg=$_G_unquoted_arg + ;; + esac + + if test -n "$func_quote_for_eval_result"; then + func_append func_quote_for_eval_result " $_G_quoted_arg" + else + func_append func_quote_for_eval_result "$_G_quoted_arg" + fi + shift + done +} + + +# func_quote_for_expand ARG +# ------------------------- +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + $debug_cmd + + case $1 in + *[\\\`\"]*) + _G_arg=`$ECHO "$1" | $SED \ + -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; + *) + _G_arg=$1 ;; + esac + + case $_G_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + _G_arg=\"$_G_arg\" + ;; + esac + + func_quote_for_expand_result=$_G_arg +} + + +# func_stripname PREFIX SUFFIX NAME +# --------------------------------- +# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_stripname () + { + $debug_cmd + + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary variable first. + func_stripname_result=$3 + func_stripname_result=${func_stripname_result#"$1"} + func_stripname_result=${func_stripname_result%"$2"} + }' +else + func_stripname () + { + $debug_cmd + + case $2 in + .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; + *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; + esac + } +fi + + +# func_show_eval CMD [FAIL_EXP] +# ----------------------------- +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + func_quote_for_expand "$_G_cmd" + eval "func_notquiet $func_quote_for_expand_result" + + $opt_dry_run || { + eval "$_G_cmd" + _G_status=$? + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_show_eval_locale CMD [FAIL_EXP] +# ------------------------------------ +# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + $debug_cmd + + _G_cmd=$1 + _G_fail_exp=${2-':'} + + $opt_quiet || { + func_quote_for_expand "$_G_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + $opt_dry_run || { + eval "$_G_user_locale + $_G_cmd" + _G_status=$? + eval "$_G_safe_locale" + if test 0 -ne "$_G_status"; then + eval "(exit $_G_status); $_G_fail_exp" + fi + } +} + + +# func_tr_sh +# ---------- +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + $debug_cmd + + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_verbose ARG... +# ------------------- +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $debug_cmd + + $opt_verbose && func_echo "$*" + + : +} + + +# func_warn_and_continue ARG... +# ----------------------------- +# Echo program name prefixed warning message to standard error. +func_warn_and_continue () +{ + $debug_cmd + + $require_term_colors + + func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 +} + + +# func_warning CATEGORY ARG... +# ---------------------------- +# Echo program name prefixed warning message to standard error. Warning +# messages can be filtered according to CATEGORY, where this function +# elides messages where CATEGORY is not listed in the global variable +# 'opt_warning_types'. +func_warning () +{ + $debug_cmd + + # CATEGORY must be in the warning_categories list! + case " $warning_categories " in + *" $1 "*) ;; + *) func_internal_error "invalid warning category '$1'" ;; + esac + + _G_category=$1 + shift + + case " $opt_warning_types " in + *" $_G_category "*) $warning_func ${1+"$@"} ;; + esac +} + + +# func_sort_ver VER1 VER2 +# ----------------------- +# 'sort -V' is not generally available. +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +func_sort_ver () +{ + $debug_cmd + + printf '%s\n%s\n' "$1" "$2" \ + | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n +} + +# func_lt_ver PREV CURR +# --------------------- +# Return true if PREV and CURR are in the correct order according to +# func_sort_ver, otherwise false. Use it like this: +# +# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." +func_lt_ver () +{ + $debug_cmd + + test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: +#! /bin/sh + +# Set a version string for this script. +scriptversion=2014-01-07.03; # UTC + +# A portable, pluggable option parser for Bourne shell. +# Written by Gary V. Vaughan, 2010 + +# Copyright (C) 2010-2015 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# 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 3 of the License, 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, see . + +# Please report bugs or propose patches to gary@gnu.org. + + +## ------ ## +## Usage. ## +## ------ ## + +# This file is a library for parsing options in your shell scripts along +# with assorted other useful supporting features that you can make use +# of too. +# +# For the simplest scripts you might need only: +# +# #!/bin/sh +# . relative/path/to/funclib.sh +# . relative/path/to/options-parser +# scriptversion=1.0 +# func_options ${1+"$@"} +# eval set dummy "$func_options_result"; shift +# ...rest of your script... +# +# In order for the '--version' option to work, you will need to have a +# suitably formatted comment like the one at the top of this file +# starting with '# Written by ' and ending with '# warranty; '. +# +# For '-h' and '--help' to work, you will also need a one line +# description of your script's purpose in a comment directly above the +# '# Written by ' line, like the one at the top of this file. +# +# The default options also support '--debug', which will turn on shell +# execution tracing (see the comment above debug_cmd below for another +# use), and '--verbose' and the func_verbose function to allow your script +# to display verbose messages only when your user has specified +# '--verbose'. +# +# After sourcing this file, you can plug processing for additional +# options by amending the variables from the 'Configuration' section +# below, and following the instructions in the 'Option parsing' +# section further down. + +## -------------- ## +## Configuration. ## +## -------------- ## + +# You should override these variables in your script after sourcing this +# file so that they reflect the customisations you have added to the +# option parser. + +# The usage line for option parsing errors and the start of '-h' and +# '--help' output messages. You can embed shell variables for delayed +# expansion at the time the message is displayed, but you will need to +# quote other shell meta-characters carefully to prevent them being +# expanded when the contents are evaled. +usage='$progpath [OPTION]...' + +# Short help message in response to '-h' and '--help'. Add to this or +# override it after sourcing this library to reflect the full set of +# options your script accepts. +usage_message="\ + --debug enable verbose shell tracing + -W, --warnings=CATEGORY + report the warnings falling in CATEGORY [all] + -v, --verbose verbosely report processing + --version print version information and exit + -h, --help print short or long help message and exit +" + +# Additional text appended to 'usage_message' in response to '--help'. +long_help_message=" +Warning categories include: + 'all' show all warnings + 'none' turn off all the warnings + 'error' warnings are treated as fatal errors" + +# Help message printed before fatal option parsing errors. +fatal_help="Try '\$progname --help' for more information." + + + +## ------------------------- ## +## Hook function management. ## +## ------------------------- ## + +# This section contains functions for adding, removing, and running hooks +# to the main code. A hook is just a named list of of function, that can +# be run in order later on. + +# func_hookable FUNC_NAME +# ----------------------- +# Declare that FUNC_NAME will run hooks added with +# 'func_add_hook FUNC_NAME ...'. +func_hookable () +{ + $debug_cmd + + func_append hookable_fns " $1" +} + + +# func_add_hook FUNC_NAME HOOK_FUNC +# --------------------------------- +# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must +# first have been declared "hookable" by a call to 'func_hookable'. +func_add_hook () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not accept hook functions." ;; + esac + + eval func_append ${1}_hooks '" $2"' +} + + +# func_remove_hook FUNC_NAME HOOK_FUNC +# ------------------------------------ +# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. +func_remove_hook () +{ + $debug_cmd + + eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' +} + + +# func_run_hooks FUNC_NAME [ARG]... +# --------------------------------- +# Run all hook functions registered to FUNC_NAME. +# It is assumed that the list of hook functions contains nothing more +# than a whitespace-delimited list of legal shell function names, and +# no effort is wasted trying to catch shell meta-characters or preserve +# whitespace. +func_run_hooks () +{ + $debug_cmd + + case " $hookable_fns " in + *" $1 "*) ;; + *) func_fatal_error "'$1' does not support hook funcions.n" ;; + esac + + eval _G_hook_fns=\$$1_hooks; shift + + for _G_hook in $_G_hook_fns; do + eval $_G_hook '"$@"' + + # store returned options list back into positional + # parameters for next 'cmd' execution. + eval _G_hook_result=\$${_G_hook}_result + eval set dummy "$_G_hook_result"; shift + done + + func_quote_for_eval ${1+"$@"} + func_run_hooks_result=$func_quote_for_eval_result +} + + + +## --------------- ## +## Option parsing. ## +## --------------- ## + +# In order to add your own option parsing hooks, you must accept the +# full positional parameter list in your hook function, remove any +# options that you action, and then pass back the remaining unprocessed +# options in '_result', escaped suitably for +# 'eval'. Like this: +# +# my_options_prep () +# { +# $debug_cmd +# +# # Extend the existing usage message. +# usage_message=$usage_message' +# -s, --silent don'\''t print informational messages +# ' +# +# func_quote_for_eval ${1+"$@"} +# my_options_prep_result=$func_quote_for_eval_result +# } +# func_add_hook func_options_prep my_options_prep +# +# +# my_silent_option () +# { +# $debug_cmd +# +# # Note that for efficiency, we parse as many options as we can +# # recognise in a loop before passing the remainder back to the +# # caller on the first unrecognised argument we encounter. +# while test $# -gt 0; do +# opt=$1; shift +# case $opt in +# --silent|-s) opt_silent=: ;; +# # Separate non-argument short options: +# -s*) func_split_short_opt "$_G_opt" +# set dummy "$func_split_short_opt_name" \ +# "-$func_split_short_opt_arg" ${1+"$@"} +# shift +# ;; +# *) set dummy "$_G_opt" "$*"; shift; break ;; +# esac +# done +# +# func_quote_for_eval ${1+"$@"} +# my_silent_option_result=$func_quote_for_eval_result +# } +# func_add_hook func_parse_options my_silent_option +# +# +# my_option_validation () +# { +# $debug_cmd +# +# $opt_silent && $opt_verbose && func_fatal_help "\ +# '--silent' and '--verbose' options are mutually exclusive." +# +# func_quote_for_eval ${1+"$@"} +# my_option_validation_result=$func_quote_for_eval_result +# } +# func_add_hook func_validate_options my_option_validation +# +# You'll alse need to manually amend $usage_message to reflect the extra +# options you parse. It's preferable to append if you can, so that +# multiple option parsing hooks can be added safely. + + +# func_options [ARG]... +# --------------------- +# All the functions called inside func_options are hookable. See the +# individual implementations for details. +func_hookable func_options +func_options () +{ + $debug_cmd + + func_options_prep ${1+"$@"} + eval func_parse_options \ + ${func_options_prep_result+"$func_options_prep_result"} + eval func_validate_options \ + ${func_parse_options_result+"$func_parse_options_result"} + + eval func_run_hooks func_options \ + ${func_validate_options_result+"$func_validate_options_result"} + + # save modified positional parameters for caller + func_options_result=$func_run_hooks_result +} + + +# func_options_prep [ARG]... +# -------------------------- +# All initialisations required before starting the option parse loop. +# Note that when calling hook functions, we pass through the list of +# positional parameters. If a hook function modifies that list, and +# needs to propogate that back to rest of this script, then the complete +# modified list must be put in 'func_run_hooks_result' before +# returning. +func_hookable func_options_prep +func_options_prep () +{ + $debug_cmd + + # Option defaults: + opt_verbose=false + opt_warning_types= + + func_run_hooks func_options_prep ${1+"$@"} + + # save modified positional parameters for caller + func_options_prep_result=$func_run_hooks_result +} + + +# func_parse_options [ARG]... +# --------------------------- +# The main option parsing loop. +func_hookable func_parse_options +func_parse_options () +{ + $debug_cmd + + func_parse_options_result= + + # this just eases exit handling + while test $# -gt 0; do + # Defer to hook functions for initial option parsing, so they + # get priority in the event of reusing an option name. + func_run_hooks func_parse_options ${1+"$@"} + + # Adjust func_parse_options positional parameters to match + eval set dummy "$func_run_hooks_result"; shift + + # Break out of the loop if we already parsed every option. + test $# -gt 0 || break + + _G_opt=$1 + shift + case $_G_opt in + --debug|-x) debug_cmd='set -x' + func_echo "enabling shell trace mode" + $debug_cmd + ;; + + --no-warnings|--no-warning|--no-warn) + set dummy --warnings none ${1+"$@"} + shift + ;; + + --warnings|--warning|-W) + test $# = 0 && func_missing_arg $_G_opt && break + case " $warning_categories $1" in + *" $1 "*) + # trailing space prevents matching last $1 above + func_append_uniq opt_warning_types " $1" + ;; + *all) + opt_warning_types=$warning_categories + ;; + *none) + opt_warning_types=none + warning_func=: + ;; + *error) + opt_warning_types=$warning_categories + warning_func=func_fatal_error + ;; + *) + func_fatal_error \ + "unsupported warning category: '$1'" + ;; + esac + shift + ;; + + --verbose|-v) opt_verbose=: ;; + --version) func_version ;; + -\?|-h) func_usage ;; + --help) func_help ;; + + # Separate optargs to long options (plugins may need this): + --*=*) func_split_equals "$_G_opt" + set dummy "$func_split_equals_lhs" \ + "$func_split_equals_rhs" ${1+"$@"} + shift + ;; + + # Separate optargs to short options: + -W*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-v*|-x*) + func_split_short_opt "$_G_opt" + set dummy "$func_split_short_opt_name" \ + "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + func_parse_options_result=$func_quote_for_eval_result +} + + +# func_validate_options [ARG]... +# ------------------------------ +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +func_hookable func_validate_options +func_validate_options () +{ + $debug_cmd + + # Display all warnings if -W was not given. + test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" + + func_run_hooks func_validate_options ${1+"$@"} + + # Bail if the options were screwed! + $exit_cmd $EXIT_FAILURE + + # save modified positional parameters for caller + func_validate_options_result=$func_run_hooks_result +} + + + +## ----------------- ## +## Helper functions. ## +## ----------------- ## + +# This section contains the helper functions used by the rest of the +# hookable option parser framework in ascii-betical order. + + +# func_fatal_help ARG... +# ---------------------- +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + eval \$ECHO \""$fatal_help"\" + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + + +# func_help +# --------- +# Echo long help message to standard output and exit. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message" + exit 0 +} + + +# func_missing_arg ARGNAME +# ------------------------ +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $debug_cmd + + func_error "Missing argument for '$1'." + exit_cmd=exit +} + + +# func_split_equals STRING +# ------------------------ +# Set func_split_equals_lhs and func_split_equals_rhs shell variables after +# splitting STRING at the '=' sign. +test -z "$_G_HAVE_XSI_OPS" \ + && (eval 'x=a/b/c; + test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ + && _G_HAVE_XSI_OPS=yes + +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=${1%%=*} + func_split_equals_rhs=${1#*=} + test "x$func_split_equals_lhs" = "x$1" \ + && func_split_equals_rhs= + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_equals () + { + $debug_cmd + + func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` + func_split_equals_rhs= + test "x$func_split_equals_lhs" = "x$1" \ + || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` + } +fi #func_split_equals + + +# func_split_short_opt SHORTOPT +# ----------------------------- +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +if test yes = "$_G_HAVE_XSI_OPS" +then + # This is an XSI compatible shell, allowing a faster implementation... + eval 'func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"} + }' +else + # ...otherwise fall back to using expr, which is often a shell builtin. + func_split_short_opt () + { + $debug_cmd + + func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` + func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` + } +fi #func_split_short_opt + + +# func_usage +# ---------- +# Echo short help message to standard output and exit. +func_usage () +{ + $debug_cmd + + func_usage_message + $ECHO "Run '$progname --help |${PAGER-more}' for full usage" + exit 0 +} + + +# func_usage_message +# ------------------ +# Echo short help message to standard output. +func_usage_message () +{ + $debug_cmd + + eval \$ECHO \""Usage: $usage"\" + echo + $SED -n 's|^# || + /^Written by/{ + x;p;x + } + h + /^Written by/q' < "$progpath" + echo + eval \$ECHO \""$usage_message"\" +} + + +# func_version +# ------------ +# Echo version message to standard output and exit. +func_version () +{ + $debug_cmd + + printf '%s\n' "$progname $scriptversion" + $SED -n ' + /(C)/!b go + :more + /\./!{ + N + s|\n# | | + b more + } + :go + /^# Written by /,/# warranty; / { + s|^# || + s|^# *$|| + s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| + p + } + /^# Written by / { + s|^# || + p + } + /^warranty; /q' < "$progpath" + + exit $? +} + + +# Local variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" +# time-stamp-time-zone: "UTC" +# End: + +# Set a version string. +scriptversion='(GNU libtool) 2.4.6' + + +# func_echo ARG... +# ---------------- +# Libtool also displays the current mode in messages, so override +# funclib.sh func_echo with this custom definition. +func_echo () +{ + $debug_cmd + + _G_message=$* + + func_echo_IFS=$IFS + IFS=$nl + for _G_line in $_G_message; do + IFS=$func_echo_IFS + $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" + done + IFS=$func_echo_IFS +} + + +# func_warning ARG... +# ------------------- +# Libtool warnings are not categorized, so override funclib.sh +# func_warning with this simpler definition. +func_warning () +{ + $debug_cmd + + $warning_func ${1+"$@"} +} + + +## ---------------- ## +## Options parsing. ## +## ---------------- ## + +# Hook in the functions to make sure our own options are parsed during +# the option parsing loop. + +usage='$progpath [OPTION]... [MODE-ARG]...' + +# Short help message in response to '-h'. +usage_message="Options: + --config show all configuration variables + --debug enable verbose shell tracing + -n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --mode=MODE use operation mode MODE + --no-warnings equivalent to '-Wnone' + --preserve-dup-deps don't remove duplicate dependency libraries + --quiet, --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + -v, --verbose print more informational messages than default + --version print version information + -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] + -h, --help, --help-all print short, long, or detailed help message +" + +# Additional text appended to 'usage_message' in response to '--help'. +func_help () +{ + $debug_cmd + + func_usage_message + $ECHO "$long_help_message + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. When passed as first option, +'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. +Try '$progname --help --mode=MODE' for a more detailed description of MODE. + +When reporting a bug, please describe a test case to reproduce it and +include the following information: + + host-triplet: $host + shell: $SHELL + compiler: $LTCC + compiler flags: $LTCFLAGS + linker: $LD (gnu? $with_gnu_ld) + version: $progname (GNU libtool) 2.4.6 + automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` + autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` + +Report bugs to . +GNU libtool home page: . +General help using GNU software: ." + exit 0 +} + + +# func_lo2o OBJECT-NAME +# --------------------- +# Transform OBJECT-NAME from a '.lo' suffix to the platform specific +# object suffix. + +lo2o=s/\\.lo\$/.$objext/ +o2lo=s/\\.$objext\$/.lo/ + +if test yes = "$_G_HAVE_XSI_OPS"; then + eval 'func_lo2o () + { + case $1 in + *.lo) func_lo2o_result=${1%.lo}.$objext ;; + * ) func_lo2o_result=$1 ;; + esac + }' + + # func_xform LIBOBJ-OR-SOURCE + # --------------------------- + # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) + # suffix to a '.lo' libtool-object suffix. + eval 'func_xform () + { + func_xform_result=${1%.*}.lo + }' +else + # ...otherwise fall back to using sed. + func_lo2o () + { + func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` + } + + func_xform () + { + func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` + } +fi + + +# func_fatal_configuration ARG... +# ------------------------------- +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func__fatal_error ${1+"$@"} \ + "See the $PACKAGE documentation for more information." \ + "Fatal configuration error." +} + + +# func_config +# ----------- +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + + +# func_features +# ------------- +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test yes = "$build_libtool_libs"; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test yes = "$build_old_libs"; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + + +# func_enable_tag TAGNAME +# ----------------------- +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname=$1 + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf=/$re_begincf/,/$re_endcf/p + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + + +# func_check_version_match +# ------------------------ +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# libtool_options_prep [ARG]... +# ----------------------------- +# Preparation for options parsed by libtool. +libtool_options_prep () +{ + $debug_mode + + # Option defaults: + opt_config=false + opt_dlopen= + opt_dry_run=false + opt_help=false + opt_mode= + opt_preserve_dup_deps=false + opt_quiet=false + + nonopt= + preserve_args= + + # Shorthand for --mode=foo, only valid as the first argument + case $1 in + clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; + compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; + execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; + finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; + install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; + link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; + uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; + esac + + # Pass back the list of options. + func_quote_for_eval ${1+"$@"} + libtool_options_prep_result=$func_quote_for_eval_result +} +func_add_hook func_options_prep libtool_options_prep + + +# libtool_parse_options [ARG]... +# --------------------------------- +# Provide handling for libtool specific options. +libtool_parse_options () +{ + $debug_cmd + + # Perform our own loop to consume as many options as possible in + # each iteration. + while test $# -gt 0; do + _G_opt=$1 + shift + case $_G_opt in + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + + --config) func_config ;; + + --dlopen|-dlopen) + opt_dlopen="${opt_dlopen+$opt_dlopen +}$1" + shift + ;; + + --preserve-dup-deps) + opt_preserve_dup_deps=: ;; + + --features) func_features ;; + + --finish) set dummy --mode finish ${1+"$@"}; shift ;; + + --help) opt_help=: ;; + + --help-all) opt_help=': help-all' ;; + + --mode) test $# = 0 && func_missing_arg $_G_opt && break + opt_mode=$1 + case $1 in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $_G_opt" + exit_cmd=exit + break + ;; + esac + shift + ;; + + --no-silent|--no-quiet) + opt_quiet=false + func_append preserve_args " $_G_opt" + ;; + + --no-warnings|--no-warning|--no-warn) + opt_warning=false + func_append preserve_args " $_G_opt" + ;; + + --no-verbose) + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --silent|--quiet) + opt_quiet=: + opt_verbose=false + func_append preserve_args " $_G_opt" + ;; + + --tag) test $# = 0 && func_missing_arg $_G_opt && break + opt_tag=$1 + func_append preserve_args " $_G_opt $1" + func_enable_tag "$1" + shift + ;; + + --verbose|-v) opt_quiet=false + opt_verbose=: + func_append preserve_args " $_G_opt" + ;; + + # An option not handled by this hook function: + *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; + esac + done + + + # save modified positional parameters for caller + func_quote_for_eval ${1+"$@"} + libtool_parse_options_result=$func_quote_for_eval_result +} +func_add_hook func_parse_options libtool_parse_options + + + +# libtool_validate_options [ARG]... +# --------------------------------- +# Perform any sanity checks on option settings and/or unconsumed +# arguments. +libtool_validate_options () +{ + # save first non-option argument + if test 0 -lt $#; then + nonopt=$1 + shift + fi + + # preserve --debug + test : = "$debug_cmd" || func_append preserve_args " --debug" + + case $host in + # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 + # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 + *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + test yes != "$build_libtool_libs" \ + && test yes != "$build_old_libs" \ + && func_fatal_configuration "not configured to build any kind of library" + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test execute != "$opt_mode"; then + func_error "unrecognized option '-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help=$help + help="Try '$progname --help --mode=$opt_mode' for more information." + } + + # Pass back the unparsed argument list + func_quote_for_eval ${1+"$@"} + libtool_validate_options_result=$func_quote_for_eval_result +} +func_add_hook func_validate_options libtool_validate_options + + +# Process options as early as possible so that --help and --version +# can return quickly. +func_options ${1+"$@"} +eval set dummy "$func_options_result"; shift + + + +## ----------- ## +## Main. ## +## ----------- ## + +magic='%%%MAGIC variable%%%' +magic_exe='%%%MAGIC EXE variable%%%' + +# Global variables. +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# func_generated_by_libtool +# True iff stdin has been generated by Libtool. This function is only +# a basic sanity check; it will hardly flush out determined imposters. +func_generated_by_libtool_p () +{ + $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool '.la' library or '.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if 'file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case $lalib_p_line in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test yes = "$lalib_p" +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + test -f "$1" && + $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $debug_cmd + + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# 'FILE.' does not work on cygwin managed mounts. +func_source () +{ + $debug_cmd + + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case $lt_sysroot:$1 in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result='='$func_stripname_result + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $debug_cmd + + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with '--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=$1 + if test yes = "$build_libtool_libs"; then + write_lobj=\'$2\' + else + write_lobj=none + fi + + if test yes = "$build_old_libs"; then + write_oldobj=\'$3\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $debug_cmd + + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result= + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result"; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $debug_cmd + + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $debug_cmd + + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $debug_cmd + + if test -z "$2" && test -n "$1"; then + func_error "Could not determine host file name corresponding to" + func_error " '$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result=$1 + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $debug_cmd + + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " '$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result=$3 + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $debug_cmd + + case $4 in + $1 ) func_to_host_path_result=$3$func_to_host_path_result + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via '$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $debug_cmd + + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $debug_cmd + + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result=$1 +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result=$func_convert_core_msys_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result=$func_convert_core_file_wine_to_w32_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_file_result=$1 + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result=$func_cygpath_result + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via '$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $debug_cmd + + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd=func_convert_path_$func_stripname_result + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $debug_cmd + + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result=$1 +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_msys_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result=$func_convert_core_path_wine_to_w32_result + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $debug_cmd + + func_to_host_path_result=$1 + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result=$func_cygpath_result + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_dll_def_p FILE +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with _LT_DLL_DEF_P in libtool.m4 +func_dll_def_p () +{ + $debug_cmd + + func_dll_def_p_tmp=`$SED -n \ + -e 's/^[ ]*//' \ + -e '/^\(;.*\)*$/d' \ + -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ + -e q \ + "$1"` + test DEF = "$func_dll_def_p_tmp" +} + + +# func_mode_compile arg... +func_mode_compile () +{ + $debug_cmd + + # Get the compilation command and the source file. + base_compile= + srcfile=$nonopt # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg=$arg + arg_mode=normal + ;; + + target ) + libobj=$arg + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify '-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs=$IFS; IFS=, + for arg in $args; do + IFS=$save_ifs + func_append_quoted lastarg "$arg" + done + IFS=$save_ifs + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg=$srcfile + srcfile=$arg + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with '-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj=$func_basename_result + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from '$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test yes = "$build_libtool_libs" \ + || func_fatal_configuration "cannot build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name '$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname=$func_basename_result + xdir=$func_dirname_result + lobj=$xdir$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test yes = "$build_old_libs"; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test no = "$compiler_c_o"; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext + lockfile=$output_obj.lock + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test yes = "$need_locks"; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test warn = "$need_locks"; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test yes = "$build_libtool_libs"; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test no != "$pic_mode"; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test yes = "$suppress_opt"; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test yes = "$build_old_libs"; then + if test yes != "$pic_mode"; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test yes = "$compiler_c_o"; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test warn = "$need_locks" && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support '-c' and '-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test no != "$need_locks"; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test compile = "$opt_mode" && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a '.o' file suitable for static linking + -static only build a '.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a 'standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix '.c' with the +library object suffix, '.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to '-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the '--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the 'install' or 'cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE use a list of object files found in FILE to specify objects + -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with '-') are ignored. + +Every other argument is treated as a filename. Files ending in '.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in '.la', then a libtool library is created, +only library objects ('.lo' files) may be specified, and '-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created +using 'ar' and 'ranlib', or on Windows using 'lib'. + +If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode '$opt_mode'" + ;; + esac + + echo + $ECHO "Try '$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test : = "$opt_help"; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | $SED -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + $SED '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $debug_cmd + + # The first argument is the command name. + cmd=$nonopt + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "'$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "'$file' was not linked with '-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir=$func_dirname_result + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir=$func_dirname_result + ;; + + *) + func_warning "'-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir=$absdir + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic=$magic + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file=$progdir/$program + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file=$progdir/$program + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if $opt_dry_run; then + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + else + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd=\$cmd$args + fi +} + +test execute = "$opt_mode" && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $debug_cmd + + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "'$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument '$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and '=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_quiet && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the '-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the '$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the '$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the '$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test finish = "$opt_mode" && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $debug_cmd + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac + then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=false + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=: ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test X-m = "X$prev" && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the '$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=: + if $isdir; then + destdir=$dest + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir=$func_dirname_result + destname=$func_basename_result + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "'$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "'$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "'$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir=$func_dirname_result + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking '$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname=$1 + shift + + srcname=$realname + test -n "$relink_command" && srcname=${realname}T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme=$stripme + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme= + ;; + esac + ;; + os2*) + case $realname in + *_dll.a) + tstripme= + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try 'ln -sf' first, because the 'ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib=$destdir/$realname + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name=$func_basename_result + instname=$dir/${name}i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest=$destfile + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to '$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test yes = "$build_old_libs"; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile=$destdir/$destname + else + func_basename "$file" + destfile=$func_basename_result + destfile=$destdir/$destfile + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext= + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=.exe + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script '$wrapper'" + + finalize=: + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "'$lib' has not been installed in '$libdir'" + finalize=false + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test no = "$fast_install" && test -n "$relink_command"; then + $opt_dry_run || { + if $finalize; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file=$func_basename_result + outputname=$tmpdir/$file + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_quiet || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink '$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file=$outputname + else + func_warning "cannot relink '$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name=$func_basename_result + + # Set up the ranlib parameters. + oldlib=$destdir/$name + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $tool_oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run '$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test install = "$opt_mode" && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $debug_cmd + + my_outputname=$1 + my_originator=$2 + my_pic_p=${3-false} + my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms=${my_outputname}S.c + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist=$output_objdir/$my_outputname.nm + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* External symbol declarations for the compiler. */\ +" + + if test yes = "$dlself"; then + func_verbose "generating symbol list for '$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from '$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols=$output_objdir/$outputname.exp + $opt_dry_run || { + $RM $export_symbols + eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from '$dlprefile'" + func_basename "$dlprefile" + name=$func_basename_result + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename= + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname"; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename=$func_basename_result + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename"; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + func_show_eval '$RM "${nlist}I"' + if test -n "$global_symbol_to_import"; then + eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[];\ +" + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ +static void lt_syminit(void) +{ + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {" + $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" + echo >> "$output_objdir/$my_dlsyms" "\ + } +}" + fi + echo >> "$output_objdir/$my_dlsyms" "\ +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{ {\"$my_originator\", (void *) 0}," + + if test -s "$nlist"I; then + echo >> "$output_objdir/$my_dlsyms" "\ + {\"@INIT@\", (void *) <_syminit}," + fi + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + $my_pic_p && pic_flag_for_symtable=" $pic_flag" + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' + + # Transform the symbol file into the correct name. + symfileobj=$output_objdir/${my_outputname}S.$objext + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for '$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $debug_cmd + + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $debug_cmd + + win32_libid_type=unknown + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + case $nm_interface in + "MS dumpbin") + if func_cygming_ms_implib_p "$1" || + func_cygming_gnu_implib_p "$1" + then + win32_nmres=import + else + win32_nmres= + fi + ;; + *) + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s|.*|import| + p + q + } + }'` + ;; + esac + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $debug_cmd + + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $debug_cmd + + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive that possess that section. Heuristic: eliminate + # all those that have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $debug_cmd + + if func_cygming_gnu_implib_p "$1"; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1"; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result= + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $debug_cmd + + f_ex_an_ar_dir=$1; shift + f_ex_an_ar_oldlib=$1 + if test yes = "$lock_old_archive_extraction"; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test yes = "$lock_old_archive_extraction"; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $debug_cmd + + my_gentop=$1; shift + my_oldlibs=${1+"$@"} + my_oldobjs= + my_xlib= + my_xabs= + my_xdir= + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib=$func_basename_result + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir=$my_gentop/$my_xlib_u + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + func_basename "$darwin_archive" + darwin_base_archive=$func_basename_result + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches; do + func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" + $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" + cd "unfat-$$/$darwin_base_archive-$darwin_arch" + func_extract_an_archive "`pwd`" "$darwin_base_archive" + cd "$darwin_curdir" + $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result=$my_oldobjs +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory where it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ that is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options that match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case \" \$* \" in + *\\ --lt-*) + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done ;; + esac + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test yes = "$fast_install"; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + \$ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) + +/* declarations of non-ANSI functions */ +#if defined __MINGW32__ +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined __CYGWIN__ +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined other_platform || defined ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined _MSC_VER +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +#elif defined __MINGW32__ +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined __CYGWIN__ +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined other platforms ... */ +#endif + +#if defined PATH_MAX +# define LT_PATHMAX PATH_MAX +#elif defined MAXPATHLEN +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ + defined __OS2__ +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free (stale); stale = 0; } \ +} while (0) + +#if defined LT_DEBUGWRAPPER +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + size_t tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined HAVE_DOS_BASED_FILE_SYSTEM + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined HAVE_DOS_BASED_FILE_SYSTEM + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = (size_t) (q - p); + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (STREQ (str, pat)) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + size_t len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + size_t orig_value_len = strlen (orig_value); + size_t add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + size_t len = strlen (new_value); + while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[--len] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -n -e ' +s/^\(.\{79\}\)\(..*\)/\1\ +\2/ +h +s/\([\\"]\)/\\\1/g +s/$/\\n/ +s/\([^\n]*\).*/ fputs ("\1", f);/p +g +D' + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $debug_cmd + + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_suncc_cstd_abi +# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! +# Several compiler flags select an ABI that is incompatible with the +# Cstd library. Avoid specifying it if any are in CXXFLAGS. +func_suncc_cstd_abi () +{ + $debug_cmd + + case " $compile_command " in + *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) + suncc_use_cstd_abi=no + ;; + *) + suncc_use_cstd_abi=yes + ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $debug_cmd + + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # what system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll that has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + os2dllname= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=false + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module=$wl-single_module + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test yes != "$build_libtool_libs" \ + && func_fatal_configuration "cannot build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg=$1 + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir=$arg + prev= + continue + ;; + dlfiles|dlprefiles) + $preload || { + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=: + } + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test no = "$dlself"; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test dlprefiles = "$prev"; then + dlself=yes + elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test dlfiles = "$prev"; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols=$arg + test -f "$arg" \ + || func_fatal_error "symbol file '$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex=$arg + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir=$arg + prev= + continue + ;; + mllvm) + # Clang does not use LLVM to link, so we can simply discard any + # '-mllvm $arg' options when doing the link step. + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + if test none != "$pic_object"; then + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + fi + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file '$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + os2dllname) + os2dllname=$arg + prev= + continue + ;; + precious_regex) + precious_files_regex=$arg + prev= + continue + ;; + release) + release=-$arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test rpath = "$prev"; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds=$arg + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg=$arg + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "'-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test X-export-symbols = "X$arg"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between '-L' and '$1'" + else + func_fatal_error "need path for '-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of '$dir'" + dir=$absdir + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test X-lc = "X$arg" || test X-lm = "X$arg"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test X-lc = "X$arg" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc due to us having libc/libc_r. + test X-lc = "X$arg" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test X-lc = "X$arg" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test X-lc = "X$arg" && continue + ;; + esac + elif test X-lc_r = "X$arg"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -mllvm) + prev=mllvm + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module=$wl-multi_module + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "'-no-install' is ignored for $host" + func_warning "assuming '-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -os2dllname) + prev=os2dllname + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs=$IFS; IFS=, + for flag in $args; do + IFS=$save_ifs + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS=$save_ifs + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # -fstack-protector* stack protector flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -specs=* GCC specs files + # -stdlib=* select c++ std lib with clang + # -fsanitize=* Clang/GCC memory and address sanitizer + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ + -specs=*|-fsanitize=*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + -Z*) + if test os2 = "`expr $host : '.*\(os2\)'`"; then + # OS/2 uses -Zxxx to specify OS/2-specific options + compiler_flags="$compiler_flags $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case $arg in + -Zlinker | -Zstack) + prev=xcompiler + ;; + esac + continue + else + # Otherwise treat like 'Some other compiler flag' below + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + fi + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test none = "$pic_object" && + test none = "$non_pic_object"; then + func_fatal_error "cannot find name of object for '$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + test none = "$pic_object" || { + # Prepend the subdirectory the object is found in. + pic_object=$xdir$pic_object + + if test dlfiles = "$prev"; then + if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test dlprefiles = "$prev"; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg=$pic_object + } + + # Non-PIC object. + if test none != "$non_pic_object"; then + # Prepend the subdirectory the object is found in. + non_pic_object=$xdir$non_pic_object + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test none = "$pic_object"; then + arg=$non_pic_object + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object=$pic_object + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir=$func_dirname_result + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "'$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test dlfiles = "$prev"; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test dlprefiles = "$prev"; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg=$func_quote_for_eval_result + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the '$prevarg' option requires an argument" + + if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname=$func_basename_result + libobjs_save=$libobjs + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + # Definition is injected by LT_CONFIG during libtool generation. + func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" + + func_dirname "$output" "/" "" + output_objdir=$func_dirname_result$objdir + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test lib = "$linkmode"; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=false + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test lib,link = "$linkmode,$pass"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs=$tmp_deplibs + fi + + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass"; then + libs=$deplibs + deplibs= + fi + if test prog = "$linkmode"; then + case $pass in + dlopen) libs=$dlfiles ;; + dlpreopen) libs=$dlprefiles ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test lib,dlpreopen = "$linkmode,$pass"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs=$dlprefiles + fi + if test dlopen = "$pass"; then + # Collect dlpreopened libraries + save_deplibs=$deplibs + deplibs= + fi + + for deplib in $libs; do + lib= + found=false + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ + |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test lib != "$linkmode" && test prog != "$linkmode"; then + func_warning "'-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test lib = "$linkmode"; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib=$searchdir/lib$name$search_ext + if test -f "$lib"; then + if test .la = "$search_ext"; then + found=: + else + found=false + fi + break 2 + fi + done + done + if $found; then + # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll=$l + done + if test "X$ll" = "X$old_library"; then # only static version available + found=false + func_dirname "$lib" "" "." + ladir=$func_dirname_result + lib=$ladir/$old_library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + else + # deplib doesn't seem to be a libtool library + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + *.ltframework) + if test prog,link = "$linkmode,$pass"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test lib = "$linkmode"; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test conv = "$pass" && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + if test scan = "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "'-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test link = "$pass"; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=false + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=: + fi + ;; + pass_all) + valid_a_lib=: + ;; + esac + if $valid_a_lib; then + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + else + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + fi + ;; + esac + continue + ;; + prog) + if test link != "$pass"; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test conv = "$pass"; then + deplibs="$deplib $deplibs" + elif test prog = "$linkmode"; then + if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=: + continue + ;; + esac # case $deplib + + $found || test -f "$lib" \ + || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "'$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir=$func_dirname_result + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test lib,link = "$linkmode,$pass" || + test prog,scan = "$linkmode,$pass" || + { test prog != "$linkmode" && test lib != "$linkmode"; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test conv = "$pass"; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + elif test prog != "$linkmode" && test lib != "$linkmode"; then + func_fatal_error "'$lib' is not a convenience library" + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test yes = "$prefer_static_libs" || + test built,no = "$prefer_static_libs,$installed"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib=$l + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for '$lib'" + fi + + # This library was specified with -dlopen. + if test dlopen = "$pass"; then + test -z "$libdir" \ + && func_fatal_error "cannot -dlopen a convenience library: '$lib'" + if test -z "$dlname" || + test yes != "$dlopen_support" || + test no = "$build_libtool_libs" + then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of '$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir=$ladir + fi + ;; + esac + func_basename "$lib" + laname=$func_basename_result + + # Find the relevant object directory and library name. + if test yes = "$installed"; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library '$lib' was moved." + dir=$ladir + absdir=$abs_ladir + libdir=$abs_ladir + else + dir=$lt_sysroot$libdir + absdir=$lt_sysroot$libdir + fi + test yes = "$hardcode_automatic" && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir=$ladir + absdir=$abs_ladir + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir=$ladir/$objdir + absdir=$abs_ladir/$objdir + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test dlpreopen = "$pass"; then + if test -z "$libdir" && test prog = "$linkmode"; then + func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" + fi + case $host in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test lib = "$linkmode"; then + deplibs="$dir/$old_library $deplibs" + elif test prog,link = "$linkmode,$pass"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test prog = "$linkmode" && test link != "$pass"; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=false + if test no != "$link_all_deplibs" || test -z "$library_names" || + test no = "$build_libtool_libs"; then + linkalldeplibs=: + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if $linkalldeplibs; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test prog,link = "$linkmode,$pass"; then + if test -n "$library_names" && + { { test no = "$prefer_static_libs" || + test built,yes = "$prefer_static_libs,$installed"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then + # Make sure the rpath contains only unique directories. + case $temp_rpath: in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if $alldeplibs && + { test pass_all = "$deplibs_check_method" || + { test yes = "$build_libtool_libs" && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test built = "$use_static_libs" && test yes = "$installed"; then + use_static_libs=no + fi + if test -n "$library_names" && + { test no = "$use_static_libs" || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc* | *os2*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test no = "$installed"; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule= + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule=$dlpremoduletest + break + fi + done + if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then + echo + if test prog = "$linkmode"; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test lib = "$linkmode" && + test yes = "$hardcode_into_libs"; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname=$1 + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname=$dlname + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc* | *os2*) + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + esac + eval soname=\"$soname_spec\" + else + soname=$realname + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot=$soname + func_basename "$soroot" + soname=$func_basename_result + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from '$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for '$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test prog = "$linkmode" || test relink != "$opt_mode"; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test no = "$hardcode_direct"; then + add=$dir/$linklib + case $host in + *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; + *-*-sysv4*uw2*) add_dir=-L$dir ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir=-L$dir ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we cannot + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library"; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add=$dir/$old_library + fi + elif test -n "$old_library"; then + add=$dir/$old_library + fi + fi + esac + elif test no = "$hardcode_minus_L"; then + case $host in + *-*-sunos*) add_shlibpath=$dir ;; + esac + add_dir=-L$dir + add=-l$name + elif test no = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + relink) + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$dir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$absdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + add_shlibpath=$dir + add=-l$name + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test yes != "$lib_linked"; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test prog = "$linkmode"; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test yes != "$hardcode_direct" && + test yes != "$hardcode_minus_L" && + test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test prog = "$linkmode" || test relink = "$opt_mode"; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test yes = "$hardcode_direct" && + test no = "$hardcode_direct_absolute"; then + add=$libdir/$linklib + elif test yes = "$hardcode_minus_L"; then + add_dir=-L$libdir + add=-l$name + elif test yes = "$hardcode_shlibpath_var"; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add=-l$name + elif test yes = "$hardcode_automatic"; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib"; then + add=$inst_prefix_dir$libdir/$linklib + else + add=$libdir/$linklib + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir=-L$libdir + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add=-l$name + fi + + if test prog = "$linkmode"; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test prog = "$linkmode"; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test unsupported != "$hardcode_direct"; then + test -n "$old_library" && linklib=$old_library + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test yes = "$build_libtool_libs"; then + # Not a shared library + if test pass_all != "$deplibs_check_method"; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system cannot link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test yes = "$module"; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test lib = "$linkmode"; then + if test -n "$dependency_libs" && + { test yes != "$hardcode_into_libs" || + test yes = "$build_old_libs" || + test yes = "$link_static"; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs=$temp_deplibs + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test no != "$link_all_deplibs"; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path=$deplib ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of '$dir'" + absdir=$dir + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names"; then + for tmp in $deplibrary_names; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl"; then + depdepl=$absdir/$objdir/$depdepl + darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" + func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" + path= + fi + fi + ;; + *) + path=-L$absdir/$objdir + ;; + esac + else + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "'$deplib' seems to be moved" + + path=-L$absdir + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test link = "$pass"; then + if test prog = "$linkmode"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs=$newdependency_libs + if test dlpreopen = "$pass"; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test dlopen != "$pass"; then + test conv = "$pass" || { + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + } + + if test prog,link = "$linkmode,$pass"; then + vars="compile_deplibs finalize_deplibs" + else + vars=deplibs + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + + # Add Sun CC postdeps if required: + test CXX = "$tagname" && { + case $host_os in + linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C++ 5.9 + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + + solaris*) + func_cc_basename "$CC" + case $func_cc_basename_result in + CC* | sunCC*) + func_suncc_cstd_abi + + if test no != "$suncc_use_cstd_abi"; then + func_append postdeps ' -library=Cstd -library=Crun' + fi + ;; + esac + ;; + esac + } + + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i= + ;; + esac + if test -n "$i"; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test prog = "$linkmode"; then + dlfiles=$newdlfiles + fi + if test prog = "$linkmode" || test lib = "$linkmode"; then + dlprefiles=$newdlprefiles + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "'-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "'-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs=$output + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form 'libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test no = "$module" \ + && func_fatal_help "libtool library '$output' must begin with 'lib'" + + if test no != "$need_lib_prefix"; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test pass_all != "$deplibs_check_method"; then + func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test no = "$dlself" \ + || func_warning "'-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test 1 -lt "$#" \ + && func_warning "ignoring multiple '-rpath's for a libtool library" + + install_libdir=$1 + + oldlibs= + if test -z "$rpath"; then + if test yes = "$build_libtool_libs"; then + # Building a libtool convenience library. + # Some compilers have problems with a '.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "'-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "'-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs=$IFS; IFS=: + set dummy $vinfo 0 0 0 + shift + IFS=$save_ifs + + test -n "$7" && \ + func_fatal_help "too many parameters to '-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major=$1 + number_minor=$2 + number_revision=$3 + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # that has an extra 1 added just for fun + # + case $version_type in + # correct linux to gnu/linux during the next big refactor + darwin|freebsd-elf|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_revision + ;; + freebsd-aout|qnx|sunos) + current=$number_major + revision=$number_minor + age=0 + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age=$number_minor + revision=$number_minor + lt_irix_increment=no + ;; + *) + func_fatal_configuration "$modename: unknown library version type '$version_type'" + ;; + esac + ;; + no) + current=$1 + revision=$2 + age=$3 + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT '$current' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION '$revision' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE '$age' must be a nonnegative integer" + func_fatal_error "'$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE '$age' is greater than the current interface number '$current'" + func_fatal_error "'$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + # On Darwin other compilers + case $CC in + nagfor*) + verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" + ;; + *) + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + esac + ;; + + freebsd-aout) + major=.$current + versuffix=.$current.$revision + ;; + + freebsd-elf) + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + irix | nonstopux) + if test no = "$lt_irix_increment"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring=$verstring_prefix$major.$revision + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test 0 -ne "$loop"; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring_prefix$major.$iface:$verstring + done + + # Before this point, $major must not contain '.'. + major=.$major + versuffix=$major.$revision + ;; + + linux) # correct to gnu/linux during the next big refactor + func_arith $current - $age + major=.$func_arith_result + versuffix=$major.$age.$revision + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=.$current.$age.$revision + verstring=$current.$age.$revision + + # Add in all the interfaces that we are compatible with. + loop=$age + while test 0 -ne "$loop"; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring=$verstring:$iface.0 + done + + # Make executables depend on our current version. + func_append verstring ":$current.0" + ;; + + qnx) + major=.$current + versuffix=.$current + ;; + + sco) + major=.$current + versuffix=.$current + ;; + + sunos) + major=.$current + versuffix=.$current.$revision + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 file systems. + func_arith $current - $age + major=$func_arith_result + versuffix=-$major + ;; + + *) + func_fatal_configuration "unknown library version type '$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring=0.0 + ;; + esac + if test no = "$need_version"; then + versuffix= + else + versuffix=.0.0 + fi + fi + + # Remove version info from name if versioning should be avoided + if test yes,no = "$avoid_version,$need_version"; then + major= + versuffix= + verstring= + fi + + # Check to see if the archive will have undefined symbols. + if test yes = "$allow_undefined"; then + if test unsupported = "$allow_undefined_flag"; then + if test yes = "$build_old_libs"; then + func_warning "undefined symbols not allowed in $host shared libraries; building static only" + build_libtool_libs=no + else + func_fatal_error "can't build $host shared library unless -no-undefined is specified" + fi + fi + else + # Don't allow undefined symbols. + allow_undefined_flag=$no_undefined_flag + fi + + fi + + func_generate_dlsyms "$libname" "$libname" : + func_append libobjs " $symfileobj" + test " " = "$libobjs" && libobjs= + + if test relink != "$opt_mode"; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) + if test -n "$precious_files_regex"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles=$dlfiles + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles=$dlprefiles + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test yes = "$build_libtool_libs"; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test yes = "$build_libtool_need_lc"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release= + versuffix= + major= + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib=$potent_lib + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | $SED 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; + *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib= + ;; + esac + fi + if test -n "$a_deplib"; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib=$potent_lib # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib= + break 2 + fi + done + done + fi + if test -n "$a_deplib"; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib"; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs= + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test yes = "$allow_libtool_libs_with_static_runtimes"; then + for i in $predeps $postdeps; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test none = "$deplibs_check_method"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test yes = "$droppeddeps"; then + if test yes = "$module"; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using 'nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** 'nm' from GNU binutils and a full rebuild may help." + fi + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test no = "$allow_undefined"; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test no = "$build_old_libs"; then + oldlibs=$output_objdir/$libname.$libext + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs=$new_libs + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test yes = "$build_libtool_libs"; then + # Remove $wl instances when linking with ld. + # FIXME: should test the right _cmds variable. + case $archive_cmds in + *\$LD\ *) wl= ;; + esac + if test yes = "$hardcode_into_libs"; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath=$finalize_rpath + test relink = "$opt_mode" || rpath=$compile_rpath$rpath + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath=$finalize_shlibpath + test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname=$1 + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname=$realname + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib=$output_objdir/$realname + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols=$output_objdir/$libname.uexp + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + func_dll_def_p "$export_symbols" || { + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols=$export_symbols + export_symbols= + always_export_symbols=yes + } + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs=$IFS; IFS='~' + for cmd1 in $cmds; do + IFS=$save_ifs + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test yes = "$try_normal_branch" \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=$output_objdir/$output_la.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS=$save_ifs + if test -n "$export_symbols_regex" && test : != "$skipped_export"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test : != "$skipped_export" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs=$tmp_deplibs + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test yes = "$compiler_needs_object" && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test : != "$skipped_export" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then + output=$output_objdir/$output_la.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then + output=$output_objdir/$output_la.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test yes = "$compiler_needs_object"; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-$k.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test -z "$objlist" || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test 1 -eq "$k"; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-$k.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-$k.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + ${skipped_export-false} && { + func_verbose "generating symbol list for '$libname.la'" + export_symbols=$output_objdir/$libname.exp + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + } + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs=$IFS; IFS='~' + for cmd in $concat_cmds; do + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + ${skipped_export-false} && { + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols=$export_symbols + test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for '$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands, which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + } + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test yes = "$module" && test -n "$module_cmds"; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs=$IFS; IFS='~' + for cmd in $cmds; do + IFS=$sp$nl + eval cmd=\"$cmd\" + IFS=$save_ifs + $opt_quiet || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS=$save_ifs + + # Restore the uninstalled library and exit + if test relink = "$opt_mode"; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test yes = "$module" || test yes = "$export_dynamic"; then + # On all known operating systems, these are identical. + dlname=$soname + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then + func_warning "'-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "'-l' and '-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "'-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "'-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "'-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object '$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj=$output + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # if reload_cmds runs $LD directly, get rid of -Wl from + # whole_archive_flag_spec and hope we can get by with turning comma + # into space. + case $reload_cmds in + *\$LD[\ \$]*) wl= ;; + esac + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags + else + gentop=$output_objdir/${obj}x + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test yes = "$build_libtool_libs" || libobjs=$non_pic_objects + + # Create the old-style object. + reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs + + output=$obj + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + test yes = "$build_libtool_libs" || { + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + } + + if test -n "$pic_flag" || test default != "$pic_mode"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output=$libobj + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "'-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "'-release' is ignored for programs" + + $preload \ + && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ + && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test CXX = "$tagname"; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " $wl-bind_at_load" + func_append finalize_command " $wl-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs=$new_libs + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath=$rpath + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs=$libdir + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir=$hardcode_libdirs + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath=$rpath + + if test -n "$libobjs" && test yes = "$build_old_libs"; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" false + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=: + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=false + ;; + *cygwin* | *mingw* ) + test yes = "$build_libtool_libs" || wrappers_required=false + ;; + *) + if test no = "$need_relink" || test yes != "$build_libtool_libs"; then + wrappers_required=false + fi + ;; + esac + $wrappers_required || { + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command=$compile_command$compile_rpath + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.$objext"; then + func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' + fi + + exit $exit_status + } + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test yes = "$no_install"; then + # We don't need to create a wrapper script. + link_command=$compile_var$compile_command$compile_rpath + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + case $hardcode_action,$fast_install in + relink,*) + # Fast installation is not supported + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "'$output' will be relinked during installation" + ;; + *,yes) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + ;; + *,no) + link_command=$compile_var$compile_command$compile_rpath + relink_command=$finalize_var$finalize_command$finalize_rpath + ;; + *,needless) + link_command=$finalize_var$compile_command$finalize_rpath + relink_command= + ;; + esac + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource=$output_path/$objdir/lt-$output_name.c + cwrapper=$output_path/$output_name.exe + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host"; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + case $build_libtool_libs in + convenience) + oldobjs="$libobjs_save $symfileobj" + addlibs=$convenience + build_libtool_libs=no + ;; + module) + oldobjs=$libobjs_save + addlibs=$old_convenience + build_libtool_libs=no + ;; + *) + oldobjs="$old_deplibs $non_pic_objects" + $preload && test -f "$symfileobj" \ + && func_append oldobjs " $symfileobj" + addlibs=$old_convenience + ;; + esac + + if test -n "$addlibs"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop=$output_objdir/${outputname}x + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase=$func_basename_result + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 + tool_oldlib=$func_to_tool_file_result + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj"; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test -z "$oldobjs"; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test yes = "$build_old_libs" && old_library=$libname.$libext + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test yes = "$hardcode_automatic"; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test yes = "$installed"; then + if test -z "$install_libdir"; then + break + fi + output=$output_objdir/${outputname}i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name=$func_basename_result + func_resolve_sysroot "$deplib" + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` + test -z "$libdir" && \ + func_fatal_error "'$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs=$newdependency_libs + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name=$func_basename_result + eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "'$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles=$newdlprefiles + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles=$newdlfiles + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles=$newdlprefiles + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test -n "$bindir"; then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result/$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that cannot go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test no,yes = "$installed,$need_relink"; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +if test link = "$opt_mode" || test relink = "$opt_mode"; then + func_mode_link ${1+"$@"} +fi + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $debug_cmd + + RM=$nonopt + files= + rmforce=false + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic=$magic + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=: ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir=$func_dirname_result + if test . = "$dir"; then + odir=$objdir + else + odir=$dir/$objdir + fi + func_basename "$file" + name=$func_basename_result + test uninstall = "$opt_mode" && odir=$dir + + # Remember odir for removal later, being careful to avoid duplicates + if test clean = "$opt_mode"; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif $rmforce; then + continue + fi + + rmfiles=$file + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case $opt_mode in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && test none != "$pic_object"; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && test none != "$non_pic_object"; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test clean = "$opt_mode"; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.$objext" + if test yes = "$fast_install" && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name"; then + func_append rmfiles " $odir/lt-$noexename.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the $objdir's in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then + func_mode_uninstall ${1+"$@"} +fi + +test -z "$opt_mode" && { + help=$generic_help + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode '$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# where we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/m17n-config.in b/m17n-config.in new file mode 100644 index 0000000..9977e5c --- /dev/null +++ b/m17n-config.in @@ -0,0 +1,145 @@ +#!/bin/sh +# m17n-config -- helper script for the m17n library. -*- coding: utf-8; -*- +# Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +# National Institute of Advanced Industrial Science and Technology (AIST) +# Registration Number H15PRO112 +# See the end for copying conditions. + +prefix=@prefix@ +exec_prefix=@exec_prefix@ + +help () +{ + echo "Usage: $0 [API-LEVEL ...] [--version | --cflags | --libs | --libtool]" + echo " API-LEVEL is CORE, SHELL (default), GUI, or FLT" +} + +if test $# -eq 0; then + help 1>&2 + exit 0 +fi + +while true; do +case $1 in +CORE) if test "x$API" = "x"; then + API="CORE"; LIBTOOLNAME="m17n-core"; + fi; + shift;; + +SHELL) if test "x$API" != "xGUI"; then + API="FLT"; LIBSHELL=" -lm17n" + if test "x$LIBFLT" = "x"; then + LIBTOOLNAME="m17n"; + else + LIBTOOLNAME="m17n m17n-flt"; + fi + fi; + shift;; + +FLT) if test "x$API" != "xGUI"; then + API="FLT"; LIBFLT=" -lm17n-flt" + if test "x$LIBSHELL" = "x"; then + LIBTOOLNAME="m17n-flt"; + else + LIBTOOLNAME="m17n m17n-flt"; + fi + fi; + shift;; + +GUI|X) API="GUI"; + LIBSHELL=" -lm17n"; LIBFLT=" -lm17n-flt"; LIBGUI=" -lm17n-gui"; + LIBTOOLNAME="m17n-gui"; + shift;; + +*) break;; +esac +done + +LIBNAME="-lm17n-core" + +if test "x$API" = "x"; then + LIBNAME="$LIBNAME -lm17n" + LIBTOOLNAME="m17n" +else + LIBNAME="$LIBNAME$LIBSHELL$LIBFLT$LIBGUI" +fi + +case $1 in +--version) + echo "@PACKAGE_VERSION@";; + +--libs) + if test "@libdir@" != "/usr/lib"; then + echo "-L@libdir@ ${LIBNAME}" + else + echo "${LIBNAME}" + fi;; + +--cflags) + if test "@includedir@" != "/usr/include"; then + echo "-I@includedir@" + fi;; + +--libtool) + for name in $LIBTOOLNAME; do + echo -n "@libdir@/lib${name}.la " + done; + echo;; +*) + help + exit 1;; +esac +exit 0 + +cat > /dev/null <], + [char* cs = nl_langinfo(CODESET); return !cs;], + am_cv_langinfo_codeset=yes, + am_cv_langinfo_codeset=no) + ]) + if test $am_cv_langinfo_codeset = yes; then + AC_DEFINE(HAVE_LANGINFO_CODESET, 1, + [Define if you have and nl_langinfo(CODESET).]) + fi +]) diff --git a/m4/gettext.m4 b/m4/gettext.m4 new file mode 100644 index 0000000..c9ae1f7 --- /dev/null +++ b/m4/gettext.m4 @@ -0,0 +1,381 @@ +# gettext.m4 serial 60 (gettext-0.17) +dnl Copyright (C) 1995-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2006. + +dnl Macro to add for using GNU gettext. + +dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). +dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The +dnl default (if it is not specified or empty) is 'no-libtool'. +dnl INTLSYMBOL should be 'external' for packages with no intl directory, +dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. +dnl If INTLSYMBOL is 'use-libtool', then a libtool library +dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, +dnl depending on --{enable,disable}-{shared,static} and on the presence of +dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library +dnl $(top_builddir)/intl/libintl.a will be created. +dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext +dnl implementations (in libc or libintl) without the ngettext() function +dnl will be ignored. If NEEDSYMBOL is specified and is +dnl 'need-formatstring-macros', then GNU gettext implementations that don't +dnl support the ISO C 99 formatstring macros will be ignored. +dnl INTLDIR is used to find the intl libraries. If empty, +dnl the value `$(top_builddir)/intl/' is used. +dnl +dnl The result of the configuration is one of three cases: +dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled +dnl and used. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 2) GNU gettext has been found in the system's C library. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 3) No internationalization, always use English msgid. +dnl Catalog format: none +dnl Catalog extension: none +dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. +dnl The use of .gmo is historical (it was needed to avoid overwriting the +dnl GNU format catalogs when building on a platform with an X/Open gettext), +dnl but we keep it in order not to force irrelevant filename changes on the +dnl maintainers. +dnl +AC_DEFUN([AM_GNU_GETTEXT], +[ + dnl Argument checking. + ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , + [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT +])])])])]) + ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , + [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT +])])])]) + define([gt_included_intl], + ifelse([$1], [external], + ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]), + [yes])) + define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], [])) + gt_NEEDS_INIT + AM_GNU_GETTEXT_NEED([$2]) + + AC_REQUIRE([AM_PO_SUBDIRS])dnl + ifelse(gt_included_intl, yes, [ + AC_REQUIRE([AM_INTL_SUBDIR])dnl + ]) + + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Sometimes libintl requires libiconv, so first search for libiconv. + dnl Ideally we would do this search only after the + dnl if test "$USE_NLS" = "yes"; then + dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT + dnl the configure script would need to contain the same shell code + dnl again, outside any 'if'. There are two solutions: + dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. + dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. + dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not + dnl documented, we avoid it. + ifelse(gt_included_intl, yes, , [ + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + ]) + + dnl Sometimes, on MacOS X, libintl requires linking with CoreFoundation. + gt_INTL_MACOSX + + dnl Set USE_NLS. + AC_REQUIRE([AM_NLS]) + + ifelse(gt_included_intl, yes, [ + BUILD_INCLUDED_LIBINTL=no + USE_INCLUDED_LIBINTL=no + ]) + LIBINTL= + LTLIBINTL= + POSUB= + + dnl Add a version number to the cache macros. + case " $gt_needs " in + *" need-formatstring-macros "*) gt_api_version=3 ;; + *" need-ngettext "*) gt_api_version=2 ;; + *) gt_api_version=1 ;; + esac + gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" + gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + ifelse(gt_included_intl, yes, [ + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH(included-gettext, + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + ]) + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If GNU gettext is available we use this. Else we have + dnl to fall back to GNU NLS library. + + if test $gt_api_version -ge 3; then + gt_revision_test_code=' +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +changequote(,)dnl +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +changequote([,])dnl +' + else + gt_revision_test_code= + fi + if test $gt_api_version -ge 2; then + gt_expression_test_code=' + * ngettext ("", "", 0)' + else + gt_expression_test_code= + fi + + AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc], + [AC_TRY_LINK([#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings;], + [bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings], + [eval "$gt_func_gnugettext_libc=yes"], + [eval "$gt_func_gnugettext_libc=no"])]) + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl Sometimes libintl requires libiconv, so first search for libiconv. + ifelse(gt_included_intl, yes, , [ + AM_ICONV_LINK + ]) + dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL + dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) + dnl because that would add "-liconv" to LIBINTL and LTLIBINTL + dnl even if libiconv doesn't exist. + AC_LIB_LINKFLAGS_BODY([intl]) + AC_CACHE_CHECK([for GNU gettext in libintl], + [$gt_func_gnugettext_libintl], + [gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + dnl Now see whether libintl exists and does not depend on libiconv. + AC_TRY_LINK([#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *);], + [bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")], + [eval "$gt_func_gnugettext_libintl=yes"], + [eval "$gt_func_gnugettext_libintl=no"]) + dnl Now see whether libintl exists and depends on libiconv. + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + AC_TRY_LINK([#include +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *);], + [bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")], + [LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + eval "$gt_func_gnugettext_libintl=yes" + ]) + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS"]) + fi + + dnl If an already present or preinstalled GNU gettext() is found, + dnl use it. But if this macro is used in GNU gettext, and GNU + dnl gettext is already preinstalled in libintl, we update this + dnl libintl. (Cf. the install rule in intl/Makefile.in.) + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ + || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + dnl Reset the values set by searching for libintl. + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + ifelse(gt_included_intl, yes, [ + if test "$gt_use_preinstalled_gnugettext" != "yes"; then + dnl GNU gettext is not found in the C library. + dnl Fall back on included GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + BUILD_INCLUDED_LIBINTL=yes + USE_INCLUDED_LIBINTL=yes + LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD" + LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD" + LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` + fi + + CATOBJEXT= + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions to use GNU gettext tools. + CATOBJEXT=.gmo + fi + ]) + + if test -n "$INTL_MACOSX_LIBS"; then + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Some extra flags are needed during linking. + LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" + LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" + fi + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + AC_DEFINE(ENABLE_NLS, 1, + [Define to 1 if translation of program messages to the user's native language + is requested.]) + else + USE_NLS=no + fi + fi + + AC_MSG_CHECKING([whether to use NLS]) + AC_MSG_RESULT([$USE_NLS]) + if test "$USE_NLS" = "yes"; then + AC_MSG_CHECKING([where the gettext function comes from]) + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + AC_MSG_RESULT([$gt_source]) + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + AC_MSG_CHECKING([how to link with libintl]) + AC_MSG_RESULT([$LIBINTL]) + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) + fi + + dnl For backward compatibility. Some packages may be using this. + AC_DEFINE(HAVE_GETTEXT, 1, + [Define if the GNU gettext() function is already present or preinstalled.]) + AC_DEFINE(HAVE_DCGETTEXT, 1, + [Define if the GNU dcgettext() function is already present or preinstalled.]) + fi + + dnl We need to process the po/ directory. + POSUB=po + fi + + ifelse(gt_included_intl, yes, [ + dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL + dnl to 'yes' because some of the testsuite requires it. + if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then + BUILD_INCLUDED_LIBINTL=yes + fi + + dnl Make all variables we use known to autoconf. + AC_SUBST(BUILD_INCLUDED_LIBINTL) + AC_SUBST(USE_INCLUDED_LIBINTL) + AC_SUBST(CATOBJEXT) + + dnl For backward compatibility. Some configure.ins may be using this. + nls_cv_header_intl= + nls_cv_header_libgt= + + dnl For backward compatibility. Some Makefiles may be using this. + DATADIRNAME=share + AC_SUBST(DATADIRNAME) + + dnl For backward compatibility. Some Makefiles may be using this. + INSTOBJEXT=.mo + AC_SUBST(INSTOBJEXT) + + dnl For backward compatibility. Some Makefiles may be using this. + GENCAT=gencat + AC_SUBST(GENCAT) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLOBJS= + if test "$USE_INCLUDED_LIBINTL" = yes; then + INTLOBJS="\$(GETTOBJS)" + fi + AC_SUBST(INTLOBJS) + + dnl Enable libtool support if the surrounding package wishes it. + INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix + AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX) + ]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLLIBS="$LIBINTL" + AC_SUBST(INTLLIBS) + + dnl Make all documented variables known to autoconf. + AC_SUBST(LIBINTL) + AC_SUBST(LTLIBINTL) + AC_SUBST(POSUB) +]) + + +dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized. +m4_define([gt_NEEDS_INIT], +[ + m4_divert_text([DEFAULTS], [gt_needs=]) + m4_define([gt_NEEDS_INIT], []) +]) + + +dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL]) +AC_DEFUN([AM_GNU_GETTEXT_NEED], +[ + m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"]) +]) + + +dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) +AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) diff --git a/m4/glibc2.m4 b/m4/glibc2.m4 new file mode 100644 index 0000000..e8f5bfe --- /dev/null +++ b/m4/glibc2.m4 @@ -0,0 +1,30 @@ +# glibc2.m4 serial 1 +dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Test for the GNU C Library, version 2.0 or newer. +# From Bruno Haible. + +AC_DEFUN([gt_GLIBC2], + [ + AC_CACHE_CHECK(whether we are using the GNU C Library 2 or newer, + ac_cv_gnu_library_2, + [AC_EGREP_CPP([Lucky GNU user], + [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ >= 2) + Lucky GNU user + #endif +#endif + ], + ac_cv_gnu_library_2=yes, + ac_cv_gnu_library_2=no) + ] + ) + AC_SUBST(GLIBC2) + GLIBC2="$ac_cv_gnu_library_2" + ] +) diff --git a/m4/glibc21.m4 b/m4/glibc21.m4 new file mode 100644 index 0000000..d95fd98 --- /dev/null +++ b/m4/glibc21.m4 @@ -0,0 +1,30 @@ +# glibc21.m4 serial 3 +dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Test for the GNU C Library, version 2.1 or newer. +# From Bruno Haible. + +AC_DEFUN([gl_GLIBC21], + [ + AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer, + ac_cv_gnu_library_2_1, + [AC_EGREP_CPP([Lucky GNU user], + [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) + Lucky GNU user + #endif +#endif + ], + ac_cv_gnu_library_2_1=yes, + ac_cv_gnu_library_2_1=no) + ] + ) + AC_SUBST(GLIBC21) + GLIBC21="$ac_cv_gnu_library_2_1" + ] +) diff --git a/m4/iconv.m4 b/m4/iconv.m4 new file mode 100644 index 0000000..66bc76f --- /dev/null +++ b/m4/iconv.m4 @@ -0,0 +1,180 @@ +# iconv.m4 serial AM6 (gettext-0.17) +dnl Copyright (C) 2000-2002, 2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], +[ + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([iconv]) +]) + +AC_DEFUN([AM_ICONV_LINK], +[ + dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and + dnl those with the standalone portable GNU libiconv installed). + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + + dnl Add $INCICONV to CPPFLAGS before performing the following checks, + dnl because if the user has installed libiconv and not disabled its use + dnl via --without-libiconv-prefix, he wants to use it. The first + dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed. + am_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) + + AC_CACHE_CHECK([for iconv], am_cv_func_iconv, [ + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + AC_TRY_LINK([#include +#include ], + [iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);], + am_cv_func_iconv=yes) + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + AC_TRY_LINK([#include +#include ], + [iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);], + am_cv_lib_iconv=yes + am_cv_func_iconv=yes) + LIBS="$am_save_LIBS" + fi + ]) + if test "$am_cv_func_iconv" = yes; then + AC_CACHE_CHECK([for working iconv], am_cv_func_iconv_works, [ + dnl This tests against bugs in AIX 5.1 and HP-UX 11.11. + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + AC_TRY_RUN([ +#include +#include +int main () +{ + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + return 1; + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + return 1; + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + return 1; + return 0; +}], [am_cv_func_iconv_works=yes], [am_cv_func_iconv_works=no], + [case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac]) + LIBS="$am_save_LIBS" + ]) + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + AC_DEFINE(HAVE_ICONV, 1, + [Define if you have the iconv() function and it works.]) + fi + if test "$am_cv_lib_iconv" = yes; then + AC_MSG_CHECKING([how to link with libiconv]) + AC_MSG_RESULT([$LIBICONV]) + else + dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV + dnl either. + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + AC_SUBST(LIBICONV) + AC_SUBST(LTLIBICONV) +]) + +AC_DEFUN([AM_ICONV], +[ + AM_ICONV_LINK + if test "$am_cv_func_iconv" = yes; then + AC_MSG_CHECKING([for iconv declaration]) + AC_CACHE_VAL(am_cv_proto_iconv, [ + AC_TRY_COMPILE([ +#include +#include +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif +], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const") + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) + am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + AC_MSG_RESULT([$]{ac_t:- + }[$]am_cv_proto_iconv) + AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1, + [Define as const if the declaration of iconv() needs const.]) + fi +]) diff --git a/m4/intdiv0.m4 b/m4/intdiv0.m4 new file mode 100644 index 0000000..8c8a670 --- /dev/null +++ b/m4/intdiv0.m4 @@ -0,0 +1,84 @@ +# intdiv0.m4 serial 2 (gettext-0.17) +dnl Copyright (C) 2002, 2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gt_INTDIV0], +[ + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + + AC_CACHE_CHECK([whether integer division by zero raises SIGFPE], + gt_cv_int_divbyzero_sigfpe, + [ + gt_cv_int_divbyzero_sigfpe= +changequote(,)dnl + case "$host_os" in + macos* | darwin[6-9]* | darwin[1-9][0-9]*) + # On MacOS X 10.2 or newer, just assume the same as when cross- + # compiling. If we were to perform the real test, 1 Crash Report + # dialog window would pop up. + case "$host_cpu" in + i[34567]86 | x86_64) + gt_cv_int_divbyzero_sigfpe="guessing yes" ;; + esac + ;; + esac +changequote([,])dnl + if test -z "$gt_cv_int_divbyzero_sigfpe"; then + AC_TRY_RUN([ +#include +#include + +static void +sigfpe_handler (int sig) +{ + /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */ + exit (sig != SIGFPE); +} + +int x = 1; +int y = 0; +int z; +int nan; + +int main () +{ + signal (SIGFPE, sigfpe_handler); +/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */ +#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP) + signal (SIGTRAP, sigfpe_handler); +#endif +/* Linux/SPARC yields signal SIGILL. */ +#if defined (__sparc__) && defined (__linux__) + signal (SIGILL, sigfpe_handler); +#endif + + z = x / y; + nan = y / y; + exit (1); +} +], gt_cv_int_divbyzero_sigfpe=yes, gt_cv_int_divbyzero_sigfpe=no, + [ + # Guess based on the CPU. +changequote(,)dnl + case "$host_cpu" in + alpha* | i[34567]86 | x86_64 | m68k | s390*) + gt_cv_int_divbyzero_sigfpe="guessing yes";; + *) + gt_cv_int_divbyzero_sigfpe="guessing no";; + esac +changequote([,])dnl + ]) + fi + ]) + case "$gt_cv_int_divbyzero_sigfpe" in + *yes) value=1;; + *) value=0;; + esac + AC_DEFINE_UNQUOTED(INTDIV0_RAISES_SIGFPE, $value, + [Define if integer division by zero raises signal SIGFPE.]) +]) diff --git a/m4/intl.m4 b/m4/intl.m4 new file mode 100644 index 0000000..934408b --- /dev/null +++ b/m4/intl.m4 @@ -0,0 +1,285 @@ +# intl.m4 serial 8 (gettext-0.17) +dnl Copyright (C) 1995-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2006. + +AC_PREREQ(2.52) + +dnl Checks for all prerequisites of the intl subdirectory, +dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS, +dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL. +AC_DEFUN([AM_INTL_SUBDIR], +[ + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + AC_REQUIRE([gt_GLIBC2])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([gl_VISIBILITY])dnl + AC_REQUIRE([gt_INTL_SUBDIR_CORE])dnl + AC_REQUIRE([AC_TYPE_LONG_LONG_INT])dnl + AC_REQUIRE([gt_TYPE_WCHAR_T])dnl + AC_REQUIRE([gt_TYPE_WINT_T])dnl + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gt_TYPE_INTMAX_T]) + AC_REQUIRE([gt_PRINTF_POSIX]) + AC_REQUIRE([gl_GLIBC21])dnl + AC_REQUIRE([gl_XSIZE])dnl + AC_REQUIRE([gt_INTL_MACOSX])dnl + + AC_CHECK_TYPE([ptrdiff_t], , + [AC_DEFINE([ptrdiff_t], [long], + [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) + ]) + AC_CHECK_HEADERS([stddef.h stdlib.h string.h]) + AC_CHECK_FUNCS([asprintf fwprintf putenv setenv setlocale snprintf wcslen]) + + dnl Use the _snprintf function only if it is declared (because on NetBSD it + dnl is defined as a weak alias of snprintf; we prefer to use the latter). + gt_CHECK_DECL(_snprintf, [#include ]) + gt_CHECK_DECL(_snwprintf, [#include ]) + + dnl Use the *_unlocked functions only if they are declared. + dnl (because some of them were defined without being declared in Solaris + dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built + dnl on Solaris 2.5.1 to run on Solaris 2.6). + dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. + gt_CHECK_DECL(getc_unlocked, [#include ]) + + case $gt_cv_func_printf_posix in + *yes) HAVE_POSIX_PRINTF=1 ;; + *) HAVE_POSIX_PRINTF=0 ;; + esac + AC_SUBST([HAVE_POSIX_PRINTF]) + if test "$ac_cv_func_asprintf" = yes; then + HAVE_ASPRINTF=1 + else + HAVE_ASPRINTF=0 + fi + AC_SUBST([HAVE_ASPRINTF]) + if test "$ac_cv_func_snprintf" = yes; then + HAVE_SNPRINTF=1 + else + HAVE_SNPRINTF=0 + fi + AC_SUBST([HAVE_SNPRINTF]) + if test "$ac_cv_func_wprintf" = yes; then + HAVE_WPRINTF=1 + else + HAVE_WPRINTF=0 + fi + AC_SUBST([HAVE_WPRINTF]) + + AM_LANGINFO_CODESET + gt_LC_MESSAGES + + dnl Compilation on mingw and Cygwin needs special Makefile rules, because + dnl 1. when we install a shared library, we must arrange to export + dnl auxiliary pointer variables for every exported variable, + dnl 2. when we install a shared library and a static library simultaneously, + dnl the include file specifies __declspec(dllimport) and therefore we + dnl must arrange to define the auxiliary pointer variables for the + dnl exported variables _also_ in the static library. + if test "$enable_shared" = yes; then + case "$host_os" in + mingw* | cygwin*) is_woe32dll=yes ;; + *) is_woe32dll=no ;; + esac + else + is_woe32dll=no + fi + WOE32DLL=$is_woe32dll + AC_SUBST([WOE32DLL]) + + dnl On mingw and Cygwin, we can activate special Makefile rules which add + dnl version information to the shared libraries and executables. + case "$host_os" in + mingw* | cygwin*) is_woe32=yes ;; + *) is_woe32=no ;; + esac + WOE32=$is_woe32 + AC_SUBST([WOE32]) + if test $WOE32 = yes; then + dnl Check for a program that compiles Windows resource files. + AC_CHECK_TOOL([WINDRES], [windres]) + fi + + dnl Determine whether when creating a library, "-lc" should be passed to + dnl libtool or not. On many platforms, it is required for the libtool option + dnl -no-undefined to work. On HP-UX, however, the -lc - stored by libtool + dnl in the *.la files - makes it impossible to create multithreaded programs, + dnl because libtool also reorders the -lc to come before the -pthread, and + dnl this disables pthread_create() . + case "$host_os" in + hpux*) LTLIBC="" ;; + *) LTLIBC="-lc" ;; + esac + AC_SUBST([LTLIBC]) + + dnl Rename some macros and functions used for locking. + AH_BOTTOM([ +#define __libc_lock_t gl_lock_t +#define __libc_lock_define gl_lock_define +#define __libc_lock_define_initialized gl_lock_define_initialized +#define __libc_lock_init gl_lock_init +#define __libc_lock_lock gl_lock_lock +#define __libc_lock_unlock gl_lock_unlock +#define __libc_lock_recursive_t gl_recursive_lock_t +#define __libc_lock_define_recursive gl_recursive_lock_define +#define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized +#define __libc_lock_init_recursive gl_recursive_lock_init +#define __libc_lock_lock_recursive gl_recursive_lock_lock +#define __libc_lock_unlock_recursive gl_recursive_lock_unlock +#define glthread_in_use libintl_thread_in_use +#define glthread_lock_init libintl_lock_init +#define glthread_lock_lock libintl_lock_lock +#define glthread_lock_unlock libintl_lock_unlock +#define glthread_lock_destroy libintl_lock_destroy +#define glthread_rwlock_init libintl_rwlock_init +#define glthread_rwlock_rdlock libintl_rwlock_rdlock +#define glthread_rwlock_wrlock libintl_rwlock_wrlock +#define glthread_rwlock_unlock libintl_rwlock_unlock +#define glthread_rwlock_destroy libintl_rwlock_destroy +#define glthread_recursive_lock_init libintl_recursive_lock_init +#define glthread_recursive_lock_lock libintl_recursive_lock_lock +#define glthread_recursive_lock_unlock libintl_recursive_lock_unlock +#define glthread_recursive_lock_destroy libintl_recursive_lock_destroy +#define glthread_once libintl_once +#define glthread_once_call libintl_once_call +#define glthread_once_singlethreaded libintl_once_singlethreaded +]) +]) + + +dnl Checks for the core files of the intl subdirectory: +dnl dcigettext.c +dnl eval-plural.h +dnl explodename.c +dnl finddomain.c +dnl gettextP.h +dnl gmo.h +dnl hash-string.h hash-string.c +dnl l10nflist.c +dnl libgnuintl.h.in (except the *printf stuff) +dnl loadinfo.h +dnl loadmsgcat.c +dnl localealias.c +dnl log.c +dnl plural-exp.h plural-exp.c +dnl plural.y +dnl Used by libglocale. +AC_DEFUN([gt_INTL_SUBDIR_CORE], +[ + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + AC_REQUIRE([gt_INTDIV0])dnl + AC_REQUIRE([gl_AC_TYPE_UINTMAX_T])dnl + AC_REQUIRE([gt_INTTYPES_PRI])dnl + AC_REQUIRE([gl_LOCK])dnl + + AC_TRY_LINK( + [int foo (int a) { a = __builtin_expect (a, 10); return a == 10 ? 0 : 1; }], + [], + [AC_DEFINE([HAVE_BUILTIN_EXPECT], 1, + [Define to 1 if the compiler understands __builtin_expect.])]) + + AC_CHECK_HEADERS([argz.h inttypes.h limits.h unistd.h sys/param.h]) + AC_CHECK_FUNCS([getcwd getegid geteuid getgid getuid mempcpy munmap \ + stpcpy strcasecmp strdup strtoul tsearch argz_count argz_stringify \ + argz_next __fsetlocking]) + + dnl Use the *_unlocked functions only if they are declared. + dnl (because some of them were defined without being declared in Solaris + dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built + dnl on Solaris 2.5.1 to run on Solaris 2.6). + dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. + gt_CHECK_DECL(feof_unlocked, [#include ]) + gt_CHECK_DECL(fgets_unlocked, [#include ]) + + AM_ICONV + + dnl glibc >= 2.4 has a NL_LOCALE_NAME macro when _GNU_SOURCE is defined, + dnl and a _NL_LOCALE_NAME macro always. + AC_CACHE_CHECK([for NL_LOCALE_NAME macro], gt_cv_nl_locale_name, + [AC_TRY_LINK([#include +#include ], + [char* cs = nl_langinfo(_NL_LOCALE_NAME(LC_MESSAGES)); + return !cs; + ], + gt_cv_nl_locale_name=yes, + gt_cv_nl_locale_name=no) + ]) + if test $gt_cv_nl_locale_name = yes; then + AC_DEFINE(HAVE_NL_LOCALE_NAME, 1, + [Define if you have and it defines the NL_LOCALE_NAME macro if _GNU_SOURCE is defined.]) + fi + + dnl intl/plural.c is generated from intl/plural.y. It requires bison, + dnl because plural.y uses bison specific features. It requires at least + dnl bison-1.26 because earlier versions generate a plural.c that doesn't + dnl compile. + dnl bison is only needed for the maintainer (who touches plural.y). But in + dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put + dnl the rule in general Makefile. Now, some people carelessly touch the + dnl files or have a broken "make" program, hence the plural.c rule will + dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not + dnl present or too old. + AC_CHECK_PROGS([INTLBISON], [bison]) + if test -z "$INTLBISON"; then + ac_verc_fail=yes + else + dnl Found it, now check the version. + AC_MSG_CHECKING([version of bison]) +changequote(<<,>>)dnl + ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` + case $ac_prog_version in + '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; + 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) +changequote([,])dnl + ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; + *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; + esac + AC_MSG_RESULT([$ac_prog_version]) + fi + if test $ac_verc_fail = yes; then + INTLBISON=: + fi +]) + + +dnl gt_CHECK_DECL(FUNC, INCLUDES) +dnl Check whether a function is declared. +AC_DEFUN([gt_CHECK_DECL], +[ + AC_CACHE_CHECK([whether $1 is declared], ac_cv_have_decl_$1, + [AC_TRY_COMPILE([$2], [ +#ifndef $1 + char *p = (char *) $1; +#endif +], ac_cv_have_decl_$1=yes, ac_cv_have_decl_$1=no)]) + if test $ac_cv_have_decl_$1 = yes; then + gt_value=1 + else + gt_value=0 + fi + AC_DEFINE_UNQUOTED([HAVE_DECL_]translit($1, [a-z], [A-Z]), [$gt_value], + [Define to 1 if you have the declaration of `$1', and to 0 if you don't.]) +]) diff --git a/m4/intlmacosx.m4 b/m4/intlmacosx.m4 new file mode 100644 index 0000000..d3f0d90 --- /dev/null +++ b/m4/intlmacosx.m4 @@ -0,0 +1,51 @@ +# intlmacosx.m4 serial 1 (gettext-0.17) +dnl Copyright (C) 2004-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Checks for special options needed on MacOS X. +dnl Defines INTL_MACOSX_LIBS. +AC_DEFUN([gt_INTL_MACOSX], +[ + dnl Check for API introduced in MacOS X 10.2. + AC_CACHE_CHECK([for CFPreferencesCopyAppValue], + gt_cv_func_CFPreferencesCopyAppValue, + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_TRY_LINK([#include ], + [CFPreferencesCopyAppValue(NULL, NULL)], + [gt_cv_func_CFPreferencesCopyAppValue=yes], + [gt_cv_func_CFPreferencesCopyAppValue=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], 1, + [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) + fi + dnl Check for API introduced in MacOS X 10.3. + AC_CACHE_CHECK([for CFLocaleCopyCurrent], gt_cv_func_CFLocaleCopyCurrent, + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_TRY_LINK([#include ], [CFLocaleCopyCurrent();], + [gt_cv_func_CFLocaleCopyCurrent=yes], + [gt_cv_func_CFLocaleCopyCurrent=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], 1, + [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + AC_SUBST([INTL_MACOSX_LIBS]) +]) diff --git a/m4/intmax.m4 b/m4/intmax.m4 new file mode 100644 index 0000000..ce7a8a4 --- /dev/null +++ b/m4/intmax.m4 @@ -0,0 +1,33 @@ +# intmax.m4 serial 3 (gettext-0.16) +dnl Copyright (C) 2002-2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether the system has the 'intmax_t' type, but don't attempt to +dnl find a replacement if it is lacking. + +AC_DEFUN([gt_TYPE_INTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_CACHE_CHECK(for intmax_t, gt_cv_c_intmax_t, + [AC_TRY_COMPILE([ +#include +#include +#if HAVE_STDINT_H_WITH_UINTMAX +#include +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +#include +#endif +], [intmax_t x = -1; + return !x;], + gt_cv_c_intmax_t=yes, + gt_cv_c_intmax_t=no)]) + if test $gt_cv_c_intmax_t = yes; then + AC_DEFINE(HAVE_INTMAX_T, 1, + [Define if you have the 'intmax_t' type in or .]) + fi +]) diff --git a/m4/inttypes-pri.m4 b/m4/inttypes-pri.m4 new file mode 100644 index 0000000..7c7f894 --- /dev/null +++ b/m4/inttypes-pri.m4 @@ -0,0 +1,36 @@ +# inttypes-pri.m4 serial 4 (gettext-0.16) +dnl Copyright (C) 1997-2002, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_PREREQ(2.52) + +# Define PRI_MACROS_BROKEN if exists and defines the PRI* +# macros to non-string values. This is the case on AIX 4.3.3. + +AC_DEFUN([gt_INTTYPES_PRI], +[ + AC_CHECK_HEADERS([inttypes.h]) + if test $ac_cv_header_inttypes_h = yes; then + AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken], + gt_cv_inttypes_pri_broken, + [ + AC_TRY_COMPILE([#include +#ifdef PRId32 +char *p = PRId32; +#endif +], [], gt_cv_inttypes_pri_broken=no, gt_cv_inttypes_pri_broken=yes) + ]) + fi + if test "$gt_cv_inttypes_pri_broken" = yes; then + AC_DEFINE_UNQUOTED(PRI_MACROS_BROKEN, 1, + [Define if exists and defines unusable PRI* macros.]) + PRI_MACROS_BROKEN=1 + else + PRI_MACROS_BROKEN=0 + fi + AC_SUBST([PRI_MACROS_BROKEN]) +]) diff --git a/m4/inttypes_h.m4 b/m4/inttypes_h.m4 new file mode 100644 index 0000000..edc8ecb --- /dev/null +++ b/m4/inttypes_h.m4 @@ -0,0 +1,26 @@ +# inttypes_h.m4 serial 7 +dnl Copyright (C) 1997-2004, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_INTTYPES_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_INTTYPES_H], +[ + AC_CACHE_CHECK([for inttypes.h], gl_cv_header_inttypes_h, + [AC_TRY_COMPILE( + [#include +#include ], + [uintmax_t i = (uintmax_t) -1; return !i;], + gl_cv_header_inttypes_h=yes, + gl_cv_header_inttypes_h=no)]) + if test $gl_cv_header_inttypes_h = yes; then + AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H_WITH_UINTMAX, 1, + [Define if exists, doesn't clash with , + and declares uintmax_t. ]) + fi +]) diff --git a/m4/lcmessage.m4 b/m4/lcmessage.m4 new file mode 100644 index 0000000..19aa77e --- /dev/null +++ b/m4/lcmessage.m4 @@ -0,0 +1,30 @@ +# lcmessage.m4 serial 4 (gettext-0.14.2) +dnl Copyright (C) 1995-2002, 2004-2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995. + +# Check whether LC_MESSAGES is available in . + +AC_DEFUN([gt_LC_MESSAGES], +[ + AC_CACHE_CHECK([for LC_MESSAGES], gt_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include ], [return LC_MESSAGES], + gt_cv_val_LC_MESSAGES=yes, gt_cv_val_LC_MESSAGES=no)]) + if test $gt_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES, 1, + [Define if your file defines LC_MESSAGES.]) + fi +]) diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4 new file mode 100644 index 0000000..96c4e2c --- /dev/null +++ b/m4/lib-ld.m4 @@ -0,0 +1,110 @@ +# lib-ld.m4 serial 3 (gettext-0.13) +dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Subroutines of libtool.m4, +dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision +dnl with libtool.m4. + +dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. +AC_DEFUN([AC_LIB_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +case `$LD -v 2>&1 conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]* | [A-Za-z]:[\\/]*)] + [re_direlt='/[^/][^/]*/\.\./'] + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(acl_cv_path_LD, +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break ;; + *) + test "$with_gnu_ld" != yes && break ;; + esac + fi + done + IFS="$ac_save_ifs" +else + acl_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$acl_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_LIB_PROG_LD_GNU +]) diff --git a/m4/lib-link.m4 b/m4/lib-link.m4 new file mode 100644 index 0000000..e3d26fc --- /dev/null +++ b/m4/lib-link.m4 @@ -0,0 +1,709 @@ +# lib-link.m4 serial 13 (gettext-0.17) +dnl Copyright (C) 2001-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_PREREQ(2.54) + +dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and +dnl augments the CPPFLAGS variable. +dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname +dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + define([Name],[translit([$1],[./-], [___])]) + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + ac_cv_lib[]Name[]_libs="$LIB[]NAME" + ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" + ac_cv_lib[]Name[]_cppflags="$INC[]NAME" + ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX" + ]) + LIB[]NAME="$ac_cv_lib[]Name[]_libs" + LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" + INC[]NAME="$ac_cv_lib[]Name[]_cppflags" + LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + AC_SUBST([LIB]NAME[_PREFIX]) + dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the + dnl results of this search when this library appears as a dependency. + HAVE_LIB[]NAME=yes + undefine([Name]) + undefine([NAME]) +]) + +dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode) +dnl searches for libname and the libraries corresponding to explicit and +dnl implicit dependencies, together with the specified include files and +dnl the ability to compile and link the specified testcode. If found, it +dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and +dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and +dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs +dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. +dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname +dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + define([Name],[translit([$1],[./-], [___])]) + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + + dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + + dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, + dnl because if the user has installed lib[]Name and not disabled its use + dnl via --without-lib[]Name-prefix, he wants to use it. + ac_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + + AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ + ac_save_LIBS="$LIBS" + LIBS="$LIBS $LIB[]NAME" + AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no]) + LIBS="$ac_save_LIBS" + ]) + if test "$ac_cv_lib[]Name" = yes; then + HAVE_LIB[]NAME=yes + AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.]) + AC_MSG_CHECKING([how to link with lib[]$1]) + AC_MSG_RESULT([$LIB[]NAME]) + else + HAVE_LIB[]NAME=no + dnl If $LIB[]NAME didn't lead to a usable library, we don't need + dnl $INC[]NAME either. + CPPFLAGS="$ac_save_CPPFLAGS" + LIB[]NAME= + LTLIB[]NAME= + LIB[]NAME[]_PREFIX= + fi + AC_SUBST([HAVE_LIB]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + AC_SUBST([LIB]NAME[_PREFIX]) + undefine([Name]) + undefine([NAME]) +]) + +dnl Determine the platform dependent parameters needed to use rpath: +dnl acl_libext, +dnl acl_shlibext, +dnl acl_hardcode_libdir_flag_spec, +dnl acl_hardcode_libdir_separator, +dnl acl_hardcode_direct, +dnl acl_hardcode_minus_L. +AC_DEFUN([AC_LIB_RPATH], +[ + dnl Tell automake >= 1.10 to complain if config.rpath is missing. + m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) + AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS + AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld + AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host + AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir + AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [ + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + ]) + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + dnl Determine whether the user wants rpath handling at all. + AC_ARG_ENABLE(rpath, + [ --disable-rpath do not hardcode runtime library paths], + :, enable_rpath=yes) +]) + +dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. +dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found +dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_LINKFLAGS_BODY], +[ + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + dnl Autoconf >= 2.61 supports dots in --with options. + define([N_A_M_E],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit([$1],[.],[_])],[$1])]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib]N_A_M_E[-prefix], +[ --with-lib]N_A_M_E[-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib + --without-lib]N_A_M_E[-prefix don't search for lib$1 in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi +]) + dnl Search the library and its dependencies in $additional_libdir and + dnl $LDFLAGS. Using breadth-first-seach. + LIB[]NAME= + LTLIB[]NAME= + INC[]NAME= + LIB[]NAME[]_PREFIX= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='$1 $2' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + dnl See if it was already located by an earlier AC_LIB_LINKFLAGS + dnl or AC_LIB_HAVE_LINKFLAGS call. + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" + else + dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined + dnl that this library doesn't exist. So just drop it. + : + fi + else + dnl Search the library lib$name in $additional_libdir and $LDFLAGS + dnl and the already constructed $LIBNAME/$LTLIBNAME. + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + dnl The same code as in the loop below: + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + dnl Found the library. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + dnl Linking with a shared library. We attempt to hardcode its + dnl directory into the executable's runpath, unless it's the + dnl standard /usr/lib. + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then + dnl No hardcoding is needed. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + dnl The hardcoding into $LIBNAME is system dependent. + if test "$acl_hardcode_direct" = yes; then + dnl Using DIR/libNAME.so during linking hardcodes DIR into the + dnl resulting binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + dnl Rely on "-L$found_dir". + dnl But don't add it if it's already contained in the LDFLAGS + dnl or the already constructed $LIBNAME + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH + dnl here, because this doesn't fit in flags passed to the + dnl compiler. So give up. No hardcoding. This affects only + dnl very old systems. + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + dnl Linking with a static library. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" + else + dnl We shouldn't come here, but anyway it's good to have a + dnl fallback. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" + fi + fi + dnl Assume the include files are nearby. + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + LIB[]NAME[]_PREFIX="$basedir" + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + dnl Potentially add $additional_includedir to $INCNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's /usr/local/include and we are using GCC on Linux, + dnl 3. if it's already present in $CPPFLAGS or the already + dnl constructed $INCNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INC[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $INCNAME. + INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + dnl Look for dependencies. + if test -n "$found_la"; then + dnl Read the .la file. It defines the variables + dnl dlname, library_names, old_library, dependency_libs, current, + dnl age, revision, installed, dlopen, dlpreopen, libdir. + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + dnl We use only dependency_libs. + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's /usr/local/lib and we are using GCC on Linux, + dnl 3. if it's already present in $LDFLAGS or the already + dnl constructed $LIBNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LIBNAME. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LTLIBNAME. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + dnl Handle this in the next round. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + dnl Handle this in the next round. Throw away the .la's + dnl directory; it is already contained in a preceding -L + dnl option. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + dnl Most likely an immediate library name. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" + ;; + esac + done + fi + else + dnl Didn't find the library; assume it is in the system directories + dnl known to the linker and runtime loader. (All the system + dnl directories known to the linker should also be known to the + dnl runtime loader, otherwise the system is severely misconfigured.) + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user must + dnl pass all path elements in one option. We can arrange that for a + dnl single library, but not when more than one $LIBNAMEs are used. + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl. + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + else + dnl The -rpath options are cumulative. + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + dnl When using libtool, the option that works for both libraries and + dnl executables is -R. The -R options are cumulative. + for found_dir in $ltrpathdirs; do + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" + done + fi +]) + +dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, +dnl unless already present in VAR. +dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes +dnl contains two or three consecutive elements that belong together. +AC_DEFUN([AC_LIB_APPENDTOVAR], +[ + for element in [$2]; do + haveit= + for x in $[$1]; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + [$1]="${[$1]}${[$1]:+ }$element" + fi + done +]) + +dnl For those cases where a variable contains several -L and -l options +dnl referring to unknown libraries and directories, this macro determines the +dnl necessary additional linker options for the runtime path. +dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) +dnl sets LDADDVAR to linker options needed together with LIBSVALUE. +dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, +dnl otherwise linking without libtool is assumed. +AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], +[ + AC_REQUIRE([AC_LIB_RPATH]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + $1= + if test "$enable_rpath" != no; then + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode directories into the resulting + dnl binary. + rpathdirs= + next= + for opt in $2; do + if test -n "$next"; then + dir="$next" + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem"; then + rpathdirs="$rpathdirs $dir" + fi + next= + else + case $opt in + -L) next=yes ;; + -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem"; then + rpathdirs="$rpathdirs $dir" + fi + next= ;; + *) next= ;; + esac + fi + done + if test "X$rpathdirs" != "X"; then + if test -n ""$3""; then + dnl libtool is used for linking. Use -R options. + for dir in $rpathdirs; do + $1="${$1}${$1:+ }-R$dir" + done + else + dnl The linker is used for linking directly. + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user + dnl must pass all path elements in one option. + alldirs= + for dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="$flag" + else + dnl The -rpath options are cumulative. + for dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="${$1}${$1:+ }$flag" + done + fi + fi + fi + fi + fi + AC_SUBST([$1]) +]) diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4 new file mode 100644 index 0000000..a8684e1 --- /dev/null +++ b/m4/lib-prefix.m4 @@ -0,0 +1,185 @@ +# lib-prefix.m4 serial 5 (gettext-0.15) +dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and +dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't +dnl require excessive bracketing. +ifdef([AC_HELP_STRING], +[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], +[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) + +dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed +dnl to access previously installed libraries. The basic assumption is that +dnl a user will want packages to use other packages he previously installed +dnl with the same --prefix option. +dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate +dnl libraries, but is otherwise very convenient. +AC_DEFUN([AC_LIB_PREFIX], +[ + AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib-prefix], +[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib + --without-lib-prefix don't search for libraries in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi +]) + if test $use_additional = yes; then + dnl Potentially add $additional_includedir to $CPPFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's already present in $CPPFLAGS, + dnl 3. if it's /usr/local/include and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + for x in $CPPFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $CPPFLAGS. + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" + fi + fi + fi + fi + dnl Potentially add $additional_libdir to $LDFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's already present in $LDFLAGS, + dnl 3. if it's /usr/local/lib and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + for x in $LDFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LDFLAGS. + LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" + fi + fi + fi + fi + fi +]) + +dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, +dnl acl_final_exec_prefix, containing the values to which $prefix and +dnl $exec_prefix will expand at the end of the configure script. +AC_DEFUN([AC_LIB_PREPARE_PREFIX], +[ + dnl Unfortunately, prefix and exec_prefix get only finally determined + dnl at the end of configure. + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the +dnl variables prefix and exec_prefix bound to the values they will have +dnl at the end of the configure script. +AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], +[ + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + $1 + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_PREPARE_MULTILIB creates a variable acl_libdirstem, containing +dnl the basename of the libdir, either "lib" or "lib64". +AC_DEFUN([AC_LIB_PREPARE_MULTILIB], +[ + dnl There is no formal standard regarding lib and lib64. The current + dnl practice is that on a system supporting 32-bit and 64-bit instruction + dnl sets or ABIs, 64-bit libraries go under $prefix/lib64 and 32-bit + dnl libraries go under $prefix/lib. We determine the compiler's default + dnl mode by looking at the compiler's library search path. If at least + dnl of its elements ends in /lib64 or points to a directory whose absolute + dnl pathname ends in /lib64, we assume a 64-bit ABI. Otherwise we use the + dnl default, namely "lib". + acl_libdirstem=lib + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi +]) diff --git a/m4/libtool.m4 b/m4/libtool.m4 new file mode 100644 index 0000000..10ab284 --- /dev/null +++ b/m4/libtool.m4 @@ -0,0 +1,8388 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 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. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool 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 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool 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, see . +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + 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 yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # 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. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + 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 + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + 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 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + 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. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + _LT_TAGVAR(link_all_deplibs, $1)=no + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + 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 + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + 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 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/m4/lock.m4 b/m4/lock.m4 new file mode 100644 index 0000000..9111933 --- /dev/null +++ b/m4/lock.m4 @@ -0,0 +1,316 @@ +# lock.m4 serial 7 (gettext-0.17) +dnl Copyright (C) 2005-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl Tests for a multithreading library to be used. +dnl Defines at most one of the macros USE_POSIX_THREADS, USE_SOLARIS_THREADS, +dnl USE_PTH_THREADS, USE_WIN32_THREADS +dnl Sets the variables LIBTHREAD and LTLIBTHREAD to the linker options for use +dnl in a Makefile (LIBTHREAD for use without libtool, LTLIBTHREAD for use with +dnl libtool). +dnl Sets the variables LIBMULTITHREAD and LTLIBMULTITHREAD similarly, for +dnl programs that really need multithread functionality. The difference +dnl between LIBTHREAD and LIBMULTITHREAD is that on platforms supporting weak +dnl symbols, typically LIBTHREAD="" whereas LIBMULTITHREAD="-lpthread". +dnl Adds to CPPFLAGS the flag -D_REENTRANT or -D_THREAD_SAFE if needed for +dnl multithread-safe programs. + +AC_DEFUN([gl_LOCK_EARLY], +[ + AC_REQUIRE([gl_LOCK_EARLY_BODY]) +]) + +dnl The guts of gl_LOCK_EARLY. Needs to be expanded only once. + +AC_DEFUN([gl_LOCK_EARLY_BODY], +[ + dnl Ordering constraints: This macro modifies CPPFLAGS in a way that + dnl influences the result of the autoconf tests that test for *_unlocked + dnl declarations, on AIX 5 at least. Therefore it must come early. + AC_BEFORE([$0], [gl_FUNC_GLIBC_UNLOCKED_IO])dnl + AC_BEFORE([$0], [gl_ARGP])dnl + + AC_REQUIRE([AC_CANONICAL_HOST]) + dnl _GNU_SOURCE is needed for pthread_rwlock_t on glibc systems. + dnl AC_USE_SYSTEM_EXTENSIONS was introduced in autoconf 2.60 and obsoletes + dnl AC_GNU_SOURCE. + m4_ifdef([AC_USE_SYSTEM_EXTENSIONS], + [AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])], + [AC_REQUIRE([AC_GNU_SOURCE])]) + dnl Check for multithreading. + AC_ARG_ENABLE(threads, +AC_HELP_STRING([--enable-threads={posix|solaris|pth|win32}], [specify multithreading API]) +AC_HELP_STRING([--disable-threads], [build without multithread safety]), + [gl_use_threads=$enableval], + [case "$host_os" in + dnl Disable multithreading by default on OSF/1, because it interferes + dnl with fork()/exec(): When msgexec is linked with -lpthread, its child + dnl process gets an endless segmentation fault inside execvp(). + osf*) gl_use_threads=no ;; + *) gl_use_threads=yes ;; + esac + ]) + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # For using : + case "$host_os" in + osf*) + # On OSF/1, the compiler needs the flag -D_REENTRANT so that it + # groks . cc also understands the flag -pthread, but + # we don't use it because 1. gcc-2.95 doesn't understand -pthread, + # 2. putting a flag into CPPFLAGS that has an effect on the linker + # causes the AC_TRY_LINK test below to succeed unexpectedly, + # leading to wrong values of LIBTHREAD and LTLIBTHREAD. + CPPFLAGS="$CPPFLAGS -D_REENTRANT" + ;; + esac + # Some systems optimize for single-threaded programs by default, and + # need special flags to disable these optimizations. For example, the + # definition of 'errno' in . + case "$host_os" in + aix* | freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;; + solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;; + esac + fi +]) + +dnl The guts of gl_LOCK. Needs to be expanded only once. + +AC_DEFUN([gl_LOCK_BODY], +[ + AC_REQUIRE([gl_LOCK_EARLY_BODY]) + gl_threads_api=none + LIBTHREAD= + LTLIBTHREAD= + LIBMULTITHREAD= + LTLIBMULTITHREAD= + if test "$gl_use_threads" != no; then + dnl Check whether the compiler and linker support weak declarations. + AC_MSG_CHECKING([whether imported symbols can be declared weak]) + gl_have_weak=no + AC_TRY_LINK([extern void xyzzy (); +#pragma weak xyzzy], [xyzzy();], [gl_have_weak=yes]) + AC_MSG_RESULT([$gl_have_weak]) + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # On OSF/1, the compiler needs the flag -pthread or -D_REENTRANT so that + # it groks . It's added above, in gl_LOCK_EARLY_BODY. + AC_CHECK_HEADER(pthread.h, gl_have_pthread_h=yes, gl_have_pthread_h=no) + if test "$gl_have_pthread_h" = yes; then + # Other possible tests: + # -lpthreads (FSU threads, PCthreads) + # -lgthreads + gl_have_pthread= + # Test whether both pthread_mutex_lock and pthread_mutexattr_init exist + # in libc. IRIX 6.5 has the first one in both libc and libpthread, but + # the second one only in libpthread, and lock.c needs it. + AC_TRY_LINK([#include ], + [pthread_mutex_lock((pthread_mutex_t*)0); + pthread_mutexattr_init((pthread_mutexattr_t*)0);], + [gl_have_pthread=yes]) + # Test for libpthread by looking for pthread_kill. (Not pthread_self, + # since it is defined as a macro on OSF/1.) + if test -n "$gl_have_pthread"; then + # The program links fine without libpthread. But it may actually + # need to link with libpthread in order to create multiple threads. + AC_CHECK_LIB(pthread, pthread_kill, + [LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread + # On Solaris and HP-UX, most pthread functions exist also in libc. + # Therefore pthread_in_use() needs to actually try to create a + # thread: pthread_create from libc will fail, whereas + # pthread_create will actually create a thread. + case "$host_os" in + solaris* | hpux*) + AC_DEFINE([PTHREAD_IN_USE_DETECTION_HARD], 1, + [Define if the pthread_in_use() detection is hard.]) + esac + ]) + else + # Some library is needed. Try libpthread and libc_r. + AC_CHECK_LIB(pthread, pthread_kill, + [gl_have_pthread=yes + LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread + LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread]) + if test -z "$gl_have_pthread"; then + # For FreeBSD 4. + AC_CHECK_LIB(c_r, pthread_kill, + [gl_have_pthread=yes + LIBTHREAD=-lc_r LTLIBTHREAD=-lc_r + LIBMULTITHREAD=-lc_r LTLIBMULTITHREAD=-lc_r]) + fi + fi + if test -n "$gl_have_pthread"; then + gl_threads_api=posix + AC_DEFINE([USE_POSIX_THREADS], 1, + [Define if the POSIX multithreading library can be used.]) + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if test $gl_have_weak = yes; then + AC_DEFINE([USE_POSIX_THREADS_WEAK], 1, + [Define if references to the POSIX multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + # OSF/1 4.0 and MacOS X 10.1 lack the pthread_rwlock_t type and the + # pthread_rwlock_* functions. + AC_CHECK_TYPE([pthread_rwlock_t], + [AC_DEFINE([HAVE_PTHREAD_RWLOCK], 1, + [Define if the POSIX multithreading library has read/write locks.])], + [], + [#include ]) + # glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro. + AC_TRY_COMPILE([#include ], + [#if __FreeBSD__ == 4 +error "No, in FreeBSD 4.0 recursive mutexes actually don't work." +#else +int x = (int)PTHREAD_MUTEX_RECURSIVE; +return !x; +#endif], + [AC_DEFINE([HAVE_PTHREAD_MUTEX_RECURSIVE], 1, + [Define if the defines PTHREAD_MUTEX_RECURSIVE.])]) + fi + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = solaris; then + gl_have_solaristhread= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lthread" + AC_TRY_LINK([#include +#include ], + [thr_self();], + [gl_have_solaristhread=yes]) + LIBS="$gl_save_LIBS" + if test -n "$gl_have_solaristhread"; then + gl_threads_api=solaris + LIBTHREAD=-lthread + LTLIBTHREAD=-lthread + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + AC_DEFINE([USE_SOLARIS_THREADS], 1, + [Define if the old Solaris multithreading library can be used.]) + if test $gl_have_weak = yes; then + AC_DEFINE([USE_SOLARIS_THREADS_WEAK], 1, + [Define if references to the old Solaris multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + fi + fi + if test "$gl_use_threads" = pth; then + gl_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_LINKFLAGS(pth) + gl_have_pth= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lpth" + AC_TRY_LINK([#include ], [pth_self();], gl_have_pth=yes) + LIBS="$gl_save_LIBS" + if test -n "$gl_have_pth"; then + gl_threads_api=pth + LIBTHREAD="$LIBPTH" + LTLIBTHREAD="$LTLIBPTH" + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + AC_DEFINE([USE_PTH_THREADS], 1, + [Define if the GNU Pth multithreading library can be used.]) + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if test $gl_have_weak = yes; then + AC_DEFINE([USE_PTH_THREADS_WEAK], 1, + [Define if references to the GNU Pth multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + else + CPPFLAGS="$gl_save_CPPFLAGS" + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = win32; then + if { case "$host_os" in + mingw*) true;; + *) false;; + esac + }; then + gl_threads_api=win32 + AC_DEFINE([USE_WIN32_THREADS], 1, + [Define if the Win32 multithreading API can be used.]) + fi + fi + fi + fi + AC_MSG_CHECKING([for multithread API to use]) + AC_MSG_RESULT([$gl_threads_api]) + AC_SUBST(LIBTHREAD) + AC_SUBST(LTLIBTHREAD) + AC_SUBST(LIBMULTITHREAD) + AC_SUBST(LTLIBMULTITHREAD) +]) + +AC_DEFUN([gl_LOCK], +[ + AC_REQUIRE([gl_LOCK_EARLY]) + AC_REQUIRE([gl_LOCK_BODY]) + gl_PREREQ_LOCK +]) + +# Prerequisites of lib/lock.c. +AC_DEFUN([gl_PREREQ_LOCK], [ + AC_REQUIRE([AC_C_INLINE]) +]) + +dnl Survey of platforms: +dnl +dnl Platform Available Compiler Supports test-lock +dnl flavours option weak result +dnl --------------- --------- --------- -------- --------- +dnl Linux 2.4/glibc posix -lpthread Y OK +dnl +dnl GNU Hurd/glibc posix +dnl +dnl FreeBSD 5.3 posix -lc_r Y +dnl posix -lkse ? Y +dnl posix -lpthread ? Y +dnl posix -lthr Y +dnl +dnl FreeBSD 5.2 posix -lc_r Y +dnl posix -lkse Y +dnl posix -lthr Y +dnl +dnl FreeBSD 4.0,4.10 posix -lc_r Y OK +dnl +dnl NetBSD 1.6 -- +dnl +dnl OpenBSD 3.4 posix -lpthread Y OK +dnl +dnl MacOS X 10.[123] posix -lpthread Y OK +dnl +dnl Solaris 7,8,9 posix -lpthread Y Sol 7,8: 0.0; Sol 9: OK +dnl solaris -lthread Y Sol 7,8: 0.0; Sol 9: OK +dnl +dnl HP-UX 11 posix -lpthread N (cc) OK +dnl Y (gcc) +dnl +dnl IRIX 6.5 posix -lpthread Y 0.5 +dnl +dnl AIX 4.3,5.1 posix -lpthread N AIX 4: 0.5; AIX 5: OK +dnl +dnl OSF/1 4.0,5.1 posix -pthread (cc) N OK +dnl -lpthread (gcc) Y +dnl +dnl Cygwin posix -lpthread Y OK +dnl +dnl Any of the above pth -lpth 0.0 +dnl +dnl Mingw win32 N OK +dnl +dnl BeOS 5 -- +dnl +dnl The test-lock result shows what happens if in test-lock.c EXPLICIT_YIELD is +dnl turned off: +dnl OK if all three tests terminate OK, +dnl 0.5 if the first test terminates OK but the second one loops endlessly, +dnl 0.0 if the first test already loops endlessly. diff --git a/m4/longlong.m4 b/m4/longlong.m4 new file mode 100644 index 0000000..a72e53b --- /dev/null +++ b/m4/longlong.m4 @@ -0,0 +1,109 @@ +# longlong.m4 serial 13 +dnl Copyright (C) 1999-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_LONG_LONG_INT if 'long long int' works. +# This fixes a bug in Autoconf 2.61, but can be removed once we +# assume 2.62 everywhere. + +# Note: If the type 'long long int' exists but is only 32 bits large +# (as on some very old compilers), HAVE_LONG_LONG_INT will not be +# defined. In this case you can treat 'long long int' like 'long int'. + +AC_DEFUN([AC_TYPE_LONG_LONG_INT], +[ + AC_CACHE_CHECK([for long long int], [ac_cv_type_long_long_int], + [AC_LINK_IFELSE( + [_AC_TYPE_LONG_LONG_SNIPPET], + [dnl This catches a bug in Tandem NonStop Kernel (OSS) cc -O circa 2004. + dnl If cross compiling, assume the bug isn't important, since + dnl nobody cross compiles for this platform as far as we know. + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[@%:@include + @%:@ifndef LLONG_MAX + @%:@ define HALF \ + (1LL << (sizeof (long long int) * CHAR_BIT - 2)) + @%:@ define LLONG_MAX (HALF - 1 + HALF) + @%:@endif]], + [[long long int n = 1; + int i; + for (i = 0; ; i++) + { + long long int m = n << i; + if (m >> i != n) + return 1; + if (LLONG_MAX / 2 < m) + break; + } + return 0;]])], + [ac_cv_type_long_long_int=yes], + [ac_cv_type_long_long_int=no], + [ac_cv_type_long_long_int=yes])], + [ac_cv_type_long_long_int=no])]) + if test $ac_cv_type_long_long_int = yes; then + AC_DEFINE([HAVE_LONG_LONG_INT], 1, + [Define to 1 if the system has the type `long long int'.]) + fi +]) + +# Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works. +# This fixes a bug in Autoconf 2.61, but can be removed once we +# assume 2.62 everywhere. + +# Note: If the type 'unsigned long long int' exists but is only 32 bits +# large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT +# will not be defined. In this case you can treat 'unsigned long long int' +# like 'unsigned long int'. + +AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT], +[ + AC_CACHE_CHECK([for unsigned long long int], + [ac_cv_type_unsigned_long_long_int], + [AC_LINK_IFELSE( + [_AC_TYPE_LONG_LONG_SNIPPET], + [ac_cv_type_unsigned_long_long_int=yes], + [ac_cv_type_unsigned_long_long_int=no])]) + if test $ac_cv_type_unsigned_long_long_int = yes; then + AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], 1, + [Define to 1 if the system has the type `unsigned long long int'.]) + fi +]) + +# Expands to a C program that can be used to test for simultaneous support +# of 'long long' and 'unsigned long long'. We don't want to say that +# 'long long' is available if 'unsigned long long' is not, or vice versa, +# because too many programs rely on the symmetry between signed and unsigned +# integer types (excluding 'bool'). +AC_DEFUN([_AC_TYPE_LONG_LONG_SNIPPET], +[ + AC_LANG_PROGRAM( + [[/* Test preprocessor. */ + #if ! (-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + error in preprocessor; + #endif + #if ! (18446744073709551615ULL <= -1ull) + error in preprocessor; + #endif + /* Test literals. */ + long long int ll = 9223372036854775807ll; + long long int nll = -9223372036854775807LL; + unsigned long long int ull = 18446744073709551615ULL; + /* Test constant expressions. */ + typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + ? 1 : -1)]; + typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 + ? 1 : -1)]; + int i = 63;]], + [[/* Test availability of runtime routines for shift and division. */ + long long int llmax = 9223372036854775807ll; + unsigned long long int ullmax = 18446744073709551615ull; + return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) + | (llmax / ll) | (llmax % ll) + | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) + | (ullmax / ull) | (ullmax % ull));]]) +]) diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4 new file mode 100644 index 0000000..94b0829 --- /dev/null +++ b/m4/ltoptions.m4 @@ -0,0 +1,437 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# 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. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4 new file mode 100644 index 0000000..48bc934 --- /dev/null +++ b/m4/ltsugar.m4 @@ -0,0 +1,124 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# 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. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/m4/ltversion.m4 b/m4/ltversion.m4 new file mode 100644 index 0000000..fa04b52 --- /dev/null +++ b/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# 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. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4 new file mode 100644 index 0000000..c6b26f8 --- /dev/null +++ b/m4/lt~obsolete.m4 @@ -0,0 +1,99 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# 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. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/m4/nls.m4 b/m4/nls.m4 new file mode 100644 index 0000000..7967cc2 --- /dev/null +++ b/m4/nls.m4 @@ -0,0 +1,31 @@ +# nls.m4 serial 3 (gettext-0.15) +dnl Copyright (C) 1995-2003, 2005-2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ(2.50) + +AC_DEFUN([AM_NLS], +[ + AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE(nls, + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT($USE_NLS) + AC_SUBST(USE_NLS) +]) diff --git a/m4/po.m4 b/m4/po.m4 new file mode 100644 index 0000000..0734762 --- /dev/null +++ b/m4/po.m4 @@ -0,0 +1,449 @@ +# po.m4 serial 15 (gettext-0.17) +dnl Copyright (C) 1995-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ(2.50) + +dnl Checks for all prerequisites of the po subdirectory. +AC_DEFUN([AM_PO_SUBDIRS], +[ + AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake + AC_REQUIRE([AM_NLS])dnl + + dnl Release version of the gettext macros. This is used to ensure that + dnl the gettext macros and po/Makefile.in.in are in sync. + AC_SUBST([GETTEXT_MACRO_VERSION], [0.17]) + + dnl Perform the following tests also if --disable-nls has been given, + dnl because they are needed for "make dist" to work. + + dnl Search for GNU msgfmt in the PATH. + dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. + dnl The second test excludes FreeBSD msgfmt. + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + + dnl Test whether it is GNU msgfmt >= 0.15. +changequote(,)dnl + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([MSGFMT_015]) +changequote(,)dnl + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([GMSGFMT_015]) + + dnl Search for GNU xgettext 0.12 or newer in the PATH. + dnl The first test excludes Solaris xgettext and early GNU xgettext versions. + dnl The second test excludes FreeBSD xgettext. + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + dnl Remove leftover from FreeBSD xgettext call. + rm -f messages.po + + dnl Test whether it is GNU xgettext >= 0.15. +changequote(,)dnl + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac +changequote([,])dnl + AC_SUBST([XGETTEXT_015]) + + dnl Search for GNU msgmerge 0.11 or newer in the PATH. + AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, + [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :) + + dnl Installation directories. + dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we + dnl have to define it here, so that it can be used in po/Makefile. + test -n "$localedir" || localedir='${datadir}/locale' + AC_SUBST([localedir]) + + dnl Support for AM_XGETTEXT_OPTION. + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + AC_SUBST([XGETTEXT_EXTRA_OPTIONS]) + + AC_CONFIG_COMMANDS([po-directories], [[ + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + # Treat a directory as a PO directory if and only if it has a + # POTFILES.in file. This allows packages to have multiple PO + # directories under different names or in different locations. + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assigment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + # Hide the ALL_LINGUAS assigment from automake < 1.5. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + done]], + [# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake < 1.5. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + ]) +]) + +dnl Postprocesses a Makefile in a directory containing PO files. +AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], +[ + # When this code is run, in config.status, two variables have already been + # set: + # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, + # - LINGUAS is the value of the environment variable LINGUAS at configure + # time. + +changequote(,)dnl + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + # Find a way to echo strings without interpreting backslash. + if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='echo' + else + if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='printf %s\n' + else + echo_func () { + cat < "$ac_file.tmp" + if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + cat >> "$ac_file.tmp" < /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` + cat >> "$ac_file.tmp" <> "$ac_file.tmp" < +#include +/* The string "%2$d %1$d", with dollar characters protected from the shell's + dollar expansion (possibly an autoconf bug). */ +static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' }; +static char buf[100]; +int main () +{ + sprintf (buf, format, 33, 55); + return (strcmp (buf, "55 33") != 0); +}], gt_cv_func_printf_posix=yes, gt_cv_func_printf_posix=no, + [ + AC_EGREP_CPP(notposix, [ +#if defined __NetBSD__ || defined __BEOS__ || defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ + notposix +#endif + ], gt_cv_func_printf_posix="guessing no", + gt_cv_func_printf_posix="guessing yes") + ]) + ]) + case $gt_cv_func_printf_posix in + *yes) + AC_DEFINE(HAVE_POSIX_PRINTF, 1, + [Define if your printf() function supports format strings with positions.]) + ;; + esac +]) diff --git a/m4/progtest.m4 b/m4/progtest.m4 new file mode 100644 index 0000000..a56365c --- /dev/null +++ b/m4/progtest.m4 @@ -0,0 +1,92 @@ +# progtest.m4 serial 4 (gettext-0.14.2) +dnl Copyright (C) 1996-2003, 2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1996. + +AC_PREREQ(2.50) + +# Search path for a program which passes the given test. + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN([AM_PATH_PROG_WITH_TEST], +[ +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + [[\\/]]* | ?:[[\\/]]*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in ifelse([$5], , $PATH, [$5]); do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) diff --git a/m4/size_max.m4 b/m4/size_max.m4 new file mode 100644 index 0000000..6cb4868 --- /dev/null +++ b/m4/size_max.m4 @@ -0,0 +1,68 @@ +# size_max.m4 serial 6 +dnl Copyright (C) 2003, 2005-2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gl_SIZE_MAX], +[ + AC_CHECK_HEADERS(stdint.h) + dnl First test whether the system already has SIZE_MAX. + AC_MSG_CHECKING([for SIZE_MAX]) + AC_CACHE_VAL([gl_cv_size_max], [ + gl_cv_size_max= + AC_EGREP_CPP([Found it], [ +#include +#if HAVE_STDINT_H +#include +#endif +#ifdef SIZE_MAX +Found it +#endif +], gl_cv_size_max=yes) + if test -z "$gl_cv_size_max"; then + dnl Define it ourselves. Here we assume that the type 'size_t' is not wider + dnl than the type 'unsigned long'. Try hard to find a definition that can + dnl be used in a preprocessor #if, i.e. doesn't contain a cast. + AC_COMPUTE_INT([size_t_bits_minus_1], [sizeof (size_t) * CHAR_BIT - 1], + [#include +#include ], size_t_bits_minus_1=) + AC_COMPUTE_INT([fits_in_uint], [sizeof (size_t) <= sizeof (unsigned int)], + [#include ], fits_in_uint=) + if test -n "$size_t_bits_minus_1" && test -n "$fits_in_uint"; then + if test $fits_in_uint = 1; then + dnl Even though SIZE_MAX fits in an unsigned int, it must be of type + dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'. + AC_TRY_COMPILE([#include + extern size_t foo; + extern unsigned long foo; + ], [], fits_in_uint=0) + fi + dnl We cannot use 'expr' to simplify this expression, because 'expr' + dnl works only with 'long' integers in the host environment, while we + dnl might be cross-compiling from a 32-bit platform to a 64-bit platform. + if test $fits_in_uint = 1; then + gl_cv_size_max="(((1U << $size_t_bits_minus_1) - 1) * 2 + 1)" + else + gl_cv_size_max="(((1UL << $size_t_bits_minus_1) - 1) * 2 + 1)" + fi + else + dnl Shouldn't happen, but who knows... + gl_cv_size_max='((size_t)~(size_t)0)' + fi + fi + ]) + AC_MSG_RESULT([$gl_cv_size_max]) + if test "$gl_cv_size_max" != yes; then + AC_DEFINE_UNQUOTED([SIZE_MAX], [$gl_cv_size_max], + [Define as the maximum value of type 'size_t', if the system doesn't define it.]) + fi +]) + +dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in. +dnl Remove this when we can assume autoconf >= 2.61. +m4_ifdef([AC_COMPUTE_INT], [], [ + AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])]) +]) diff --git a/m4/stdint_h.m4 b/m4/stdint_h.m4 new file mode 100644 index 0000000..db9a8ac --- /dev/null +++ b/m4/stdint_h.m4 @@ -0,0 +1,26 @@ +# stdint_h.m4 serial 6 +dnl Copyright (C) 1997-2004, 2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_STDINT_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_STDINT_H], +[ + AC_CACHE_CHECK([for stdint.h], gl_cv_header_stdint_h, + [AC_TRY_COMPILE( + [#include +#include ], + [uintmax_t i = (uintmax_t) -1; return !i;], + gl_cv_header_stdint_h=yes, + gl_cv_header_stdint_h=no)]) + if test $gl_cv_header_stdint_h = yes; then + AC_DEFINE_UNQUOTED(HAVE_STDINT_H_WITH_UINTMAX, 1, + [Define if exists, doesn't clash with , + and declares uintmax_t. ]) + fi +]) diff --git a/m4/uintmax_t.m4 b/m4/uintmax_t.m4 new file mode 100644 index 0000000..641c489 --- /dev/null +++ b/m4/uintmax_t.m4 @@ -0,0 +1,30 @@ +# uintmax_t.m4 serial 10 +dnl Copyright (C) 1997-2004, 2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +AC_PREREQ(2.13) + +# Define uintmax_t to 'unsigned long' or 'unsigned long long' +# if it is not already defined in or . + +AC_DEFUN([gl_AC_TYPE_UINTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then + AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) + test $ac_cv_type_unsigned_long_long_int = yes \ + && ac_type='unsigned long long' \ + || ac_type='unsigned long' + AC_DEFINE_UNQUOTED(uintmax_t, $ac_type, + [Define to unsigned long or unsigned long long + if and don't define.]) + else + AC_DEFINE(HAVE_UINTMAX_T, 1, + [Define if you have the 'uintmax_t' type in or .]) + fi +]) diff --git a/m4/visibility.m4 b/m4/visibility.m4 new file mode 100644 index 0000000..2ff6330 --- /dev/null +++ b/m4/visibility.m4 @@ -0,0 +1,52 @@ +# visibility.m4 serial 1 (gettext-0.15) +dnl Copyright (C) 2005 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl Tests whether the compiler supports the command-line option +dnl -fvisibility=hidden and the function and variable attributes +dnl __attribute__((__visibility__("hidden"))) and +dnl __attribute__((__visibility__("default"))). +dnl Does *not* test for __visibility__("protected") - which has tricky +dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on +dnl MacOS X. +dnl Does *not* test for __visibility__("internal") - which has processor +dnl dependent semantics. +dnl Does *not* test for #pragma GCC visibility push(hidden) - which is +dnl "really only recommended for legacy code". +dnl Set the variable CFLAG_VISIBILITY. +dnl Defines and sets the variable HAVE_VISIBILITY. + +AC_DEFUN([gl_VISIBILITY], +[ + AC_REQUIRE([AC_PROG_CC]) + CFLAG_VISIBILITY= + HAVE_VISIBILITY=0 + if test -n "$GCC"; then + AC_MSG_CHECKING([for simple visibility declarations]) + AC_CACHE_VAL(gl_cv_cc_visibility, [ + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fvisibility=hidden" + AC_TRY_COMPILE( + [extern __attribute__((__visibility__("hidden"))) int hiddenvar; + extern __attribute__((__visibility__("default"))) int exportedvar; + extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void); + extern __attribute__((__visibility__("default"))) int exportedfunc (void);], + [], + gl_cv_cc_visibility=yes, + gl_cv_cc_visibility=no) + CFLAGS="$gl_save_CFLAGS"]) + AC_MSG_RESULT([$gl_cv_cc_visibility]) + if test $gl_cv_cc_visibility = yes; then + CFLAG_VISIBILITY="-fvisibility=hidden" + HAVE_VISIBILITY=1 + fi + fi + AC_SUBST([CFLAG_VISIBILITY]) + AC_SUBST([HAVE_VISIBILITY]) + AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY], + [Define to 1 or 0, depending whether the compiler supports simple visibility declarations.]) +]) diff --git a/m4/wchar_t.m4 b/m4/wchar_t.m4 new file mode 100644 index 0000000..cde2129 --- /dev/null +++ b/m4/wchar_t.m4 @@ -0,0 +1,20 @@ +# wchar_t.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether has the 'wchar_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WCHAR_T], +[ + AC_CACHE_CHECK([for wchar_t], gt_cv_c_wchar_t, + [AC_TRY_COMPILE([#include + wchar_t foo = (wchar_t)'\0';], , + gt_cv_c_wchar_t=yes, gt_cv_c_wchar_t=no)]) + if test $gt_cv_c_wchar_t = yes; then + AC_DEFINE(HAVE_WCHAR_T, 1, [Define if you have the 'wchar_t' type.]) + fi +]) diff --git a/m4/wint_t.m4 b/m4/wint_t.m4 new file mode 100644 index 0000000..af5ed93 --- /dev/null +++ b/m4/wint_t.m4 @@ -0,0 +1,28 @@ +# wint_t.m4 serial 2 (gettext-0.17) +dnl Copyright (C) 2003, 2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether has the 'wint_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WINT_T], +[ + AC_CACHE_CHECK([for wint_t], gt_cv_c_wint_t, + [AC_TRY_COMPILE([ +/* Tru64 with Desktop Toolkit C has a bug: must be included before + . + BSD/OS 4.0.1 has a bug: , and must be included + before . */ +#include +#include +#include +#include + wint_t foo = (wchar_t)'\0';], , + gt_cv_c_wint_t=yes, gt_cv_c_wint_t=no)]) + if test $gt_cv_c_wint_t = yes; then + AC_DEFINE(HAVE_WINT_T, 1, [Define if you have the 'wint_t' type.]) + fi +]) diff --git a/m4/xsize.m4 b/m4/xsize.m4 new file mode 100644 index 0000000..85bb721 --- /dev/null +++ b/m4/xsize.m4 @@ -0,0 +1,13 @@ +# xsize.m4 serial 3 +dnl Copyright (C) 2003-2004 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_XSIZE], +[ + dnl Prerequisites of lib/xsize.h. + AC_REQUIRE([gl_SIZE_MAX]) + AC_REQUIRE([AC_C_INLINE]) + AC_CHECK_HEADERS(stdint.h) +]) diff --git a/missing b/missing new file mode 100755 index 0000000..f62bbae --- /dev/null +++ b/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2013-10-28.13; # UTC + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# 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, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/po/ChangeLog b/po/ChangeLog new file mode 100644 index 0000000..5d2e083 --- /dev/null +++ b/po/ChangeLog @@ -0,0 +1,16 @@ +2010-08-27 Kenichi Handa + + * Makefile.in.in: Re-generated by autopoint. + +2010-08-27 gettextize + + * Makefile.in.in: New file, from gettext-0.17. + * Rules-quot: New file, from gettext-0.17. + * boldquot.sed: New file, from gettext-0.17. + * en@boldquot.header: New file, from gettext-0.17. + * en@quot.header: New file, from gettext-0.17. + * insert-header.sin: New file, from gettext-0.17. + * quot.sed: New file, from gettext-0.17. + * remove-potcdate.sin: New file, from gettext-0.17. + * POTFILES.in: New file. + diff --git a/po/Makefile.in.in b/po/Makefile.in.in new file mode 100644 index 0000000..fecf500 --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,429 @@ +# Makefile for PO directory in any package using GNU gettext. +# Copyright (C) 1995-1997, 2000-2007 by Ulrich Drepper +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU General Public +# License but which still want to provide support for the GNU gettext +# functionality. +# Please note that the actual code of GNU gettext is covered by the GNU +# General Public License and is *not* in the public domain. +# +# Origin: gettext-0.17 +GETTEXT_MACRO_VERSION = 0.17 + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ + +SHELL = /bin/sh +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datarootdir = @datarootdir@ +datadir = @datadir@ +localedir = @localedir@ +gettextsrcdir = $(datadir)/gettext/po + +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@ + +GMSGFMT_ = @GMSGFMT@ +GMSGFMT_no = @GMSGFMT@ +GMSGFMT_yes = @GMSGFMT_015@ +GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT)) +MSGFMT_ = @MSGFMT@ +MSGFMT_no = @MSGFMT@ +MSGFMT_yes = @MSGFMT_015@ +MSGFMT = $(MSGFMT_$(USE_MSGCTXT)) +XGETTEXT_ = @XGETTEXT@ +XGETTEXT_no = @XGETTEXT@ +XGETTEXT_yes = @XGETTEXT_015@ +XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT)) +MSGMERGE = msgmerge +MSGMERGE_UPDATE = @MSGMERGE@ --update +MSGINIT = msginit +MSGCONV = msgconv +MSGFILTER = msgfilter + +POFILES = @POFILES@ +GMOFILES = @GMOFILES@ +UPDATEPOFILES = @UPDATEPOFILES@ +DUMMYPOFILES = @DUMMYPOFILES@ +DISTFILES.common = Makefile.in.in remove-potcdate.sin \ +$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) +DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \ +$(POFILES) $(GMOFILES) \ +$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) + +POTFILES = \ + +CATALOGS = @CATALOGS@ + +# Makevars gets inserted here. (Don't remove this line!) + +.SUFFIXES: +.SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update + +.po.mo: + @echo "$(MSGFMT) -c -o $@ $<"; \ + $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ + +.po.gmo: + @lang=`echo $* | sed -e 's,.*/,,'`; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o $${lang}.gmo $${lang}.po"; \ + cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo + +.sin.sed: + sed -e '/^#/d' $< > t-$@ + mv t-$@ $@ + + +all: check-macro-version all-@USE_NLS@ + +all-yes: stamp-po +all-no: + +# Ensure that the gettext macros and this Makefile.in.in are in sync. +check-macro-version: + @test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \ + || { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \ + exit 1; \ + } + +# $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no +# internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because +# we don't want to bother translators with empty POT files). We assume that +# LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. +# In this case, stamp-po is a nop (i.e. a phony target). + +# stamp-po is a timestamp denoting the last time at which the CATALOGS have +# been loosely updated. Its purpose is that when a developer or translator +# checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, +# "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent +# invocations of "make" will do nothing. This timestamp would not be necessary +# if updating the $(CATALOGS) would always touch them; however, the rule for +# $(POFILES) has been designed to not touch files that don't need to be +# changed. +stamp-po: $(srcdir)/$(DOMAIN).pot + test ! -f $(srcdir)/$(DOMAIN).pot || \ + test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) + @test ! -f $(srcdir)/$(DOMAIN).pot || { \ + echo "touch stamp-po" && \ + echo timestamp > stamp-poT && \ + mv stamp-poT stamp-po; \ + } + +# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', +# otherwise packages like GCC can not be built if only parts of the source +# have been downloaded. + +# This target rebuilds $(DOMAIN).pot; it is an expensive operation. +# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed. +$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed + if LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null | grep -v 'libtool:' >/dev/null; then \ + package_gnu='GNU '; \ + else \ + package_gnu=''; \ + fi; \ + if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ + msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ + else \ + msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \ + fi; \ + case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + *) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --package-name="$${package_gnu}@PACKAGE@" \ + --package-version='@VERSION@' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + esac + test ! -f $(DOMAIN).po || { \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ + sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ + if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \ + else \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + else \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + } + +# This rule has no dependencies: we don't need to update $(DOMAIN).pot at +# every "make" invocation, only create it when it is missing. +# Only "make $(DOMAIN).pot-update" or "make dist" will force an update. +$(srcdir)/$(DOMAIN).pot: + $(MAKE) $(DOMAIN).pot-update + +# This target rebuilds a PO file if $(DOMAIN).pot has changed. +# Note that a PO file is not touched if it doesn't need to be changed. +$(POFILES): $(srcdir)/$(DOMAIN).pot + @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ + if test -f "$(srcdir)/$${lang}.po"; then \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot"; \ + cd $(srcdir) && $(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot; \ + else \ + $(MAKE) $${lang}.po-create; \ + fi + + +install: install-exec install-data +install-exec: +install-data: install-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + for file in $(DISTFILES.common) Makevars.template; do \ + $(INSTALL_DATA) $(srcdir)/$$file \ + $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + for file in Makevars; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +install-data-no: all +install-data-yes: all + $(mkdir_p) $(DESTDIR)$(datadir) + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ + $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ + echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ + fi; \ + done; \ + done + +install-strip: install + +installdirs: installdirs-exec installdirs-data +installdirs-exec: +installdirs-data: installdirs-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + else \ + : ; \ + fi +installdirs-data-no: +installdirs-data-yes: + $(mkdir_p) $(DESTDIR)$(datadir) + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + fi; \ + done; \ + done + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: uninstall-exec uninstall-data +uninstall-exec: +uninstall-data: uninstall-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + for file in $(DISTFILES.common) Makevars.template; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +uninstall-data-no: +uninstall-data-yes: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + done; \ + done + +check: all + +info dvi ps pdf html tags TAGS ctags CTAGS ID: + +mostlyclean: + rm -f remove-potcdate.sed + rm -f stamp-poT + rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po + rm -fr *.o + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES *.mo + +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 stamp-po $(GMOFILES) + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: + $(MAKE) update-po + @$(MAKE) dist2 +# This is a separate target because 'update-po' must be executed before. +dist2: stamp-po $(DISTFILES) + dists="$(DISTFILES)"; \ + if test "$(PACKAGE)" = "gettext-tools"; then \ + dists="$$dists Makevars.template"; \ + fi; \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + dists="$$dists $(DOMAIN).pot stamp-po"; \ + fi; \ + if test -f $(srcdir)/ChangeLog; then \ + dists="$$dists ChangeLog"; \ + fi; \ + for i in 0 1 2 3 4 5 6 7 8 9; do \ + if test -f $(srcdir)/ChangeLog.$$i; then \ + dists="$$dists ChangeLog.$$i"; \ + fi; \ + done; \ + if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ + for file in $$dists; do \ + if test -f $$file; then \ + cp -p $$file $(distdir) || exit 1; \ + else \ + cp -p $(srcdir)/$$file $(distdir) || exit 1; \ + fi; \ + done + +update-po: Makefile + $(MAKE) $(DOMAIN).pot-update + test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) + $(MAKE) update-gmo + +# General rule for creating PO files. + +.nop.po-create: + @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ + echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ + exit 1 + +# General rule for updating PO files. + +.nop.po-update: + @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ + if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ + cd $(srcdir); \ + if $(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$tmpdir/$$lang.new.po; then \ + if cmp $$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; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "msgmerge for $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +$(DUMMYPOFILES): + +update-gmo: Makefile $(GMOFILES) + @: + +Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@ + cd $(top_builddir) \ + && $(SHELL) ./config.status $(subdir)/$@.in po-directories + +force: + +# 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/Makevars b/po/Makevars new file mode 100644 index 0000000..32692ab --- /dev/null +++ b/po/Makevars @@ -0,0 +1,41 @@ +# Makefile variables for PO directory in any package using GNU gettext. + +# Usually the message domain is the same as the package name. +DOMAIN = $(PACKAGE) + +# These two variables depend on the location of this directory. +subdir = po +top_builddir = .. + +# These options get passed to xgettext. +XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ + +# This is the copyright holder that gets inserted into the header of the +# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding +# package. (Note that the msgstr strings, extracted from the package's +# sources, belong to the copyright holder of the package.) Translators are +# expected to transfer the copyright for their translations to this person +# or entity, or to disclaim their copyright. The empty string stands for +# the public domain; in this case the translators are expected to disclaim +# their copyright. +COPYRIGHT_HOLDER = Free Software Foundation, Inc. + +# This is the email address or URL to which the translators shall report +# bugs in the untranslated strings: +# - Strings which are not entire sentences, see the maintainer guidelines +# in the GNU gettext documentation, section 'Preparing Strings'. +# - Strings which use unclear terms or require additional context to be +# understood. +# - Strings which make invalid assumptions about notation of date, time or +# money. +# - Pluralisation problems. +# - Incorrect English spelling. +# - Incorrect formatting. +# It can be your email address, or a mailing list address where translators +# can write to without being subscribed, or the URL of a web page through +# which the translators can contact you. +MSGID_BUGS_ADDRESS = + +# This is the list of locale categories, beyond LC_MESSAGES, for which the +# message catalogs shall be used. It is usually empty. +EXTRA_LOCALE_CATEGORIES = diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..667e27c --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1 @@ +# List of source files which contain translatable strings. diff --git a/po/Rules-quot b/po/Rules-quot new file mode 100644 index 0000000..9c2a995 --- /dev/null +++ b/po/Rules-quot @@ -0,0 +1,47 @@ +# Special Makefile rules for English message catalogs with quotation marks. + +DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot + +.SUFFIXES: .insert-header .po-update-en + +en@quot.po-create: + $(MAKE) en@quot.po-update +en@boldquot.po-create: + $(MAKE) en@boldquot.po-update + +en@quot.po-update: en@quot.po-update-en +en@boldquot.po-update: en@boldquot.po-update-en + +.insert-header.po-update-en: + @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \ + if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + ll=`echo $$lang | sed -e 's/@.*//'`; \ + LC_ALL=C; export LC_ALL; \ + cd $(srcdir); \ + if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$ll -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) sed -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \ + if cmp $$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 "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "creation of $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +en@quot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header + +en@boldquot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header + +mostlyclean: mostlyclean-quot +mostlyclean-quot: + rm -f *.insert-header diff --git a/po/boldquot.sed b/po/boldquot.sed new file mode 100644 index 0000000..4b937aa --- /dev/null +++ b/po/boldquot.sed @@ -0,0 +1,10 @@ +s/"\([^"]*\)"/“\1”/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“”/""/g +s/“/“/g +s/”/”/g +s/‘/‘/g +s/’/’/g diff --git a/po/en@boldquot.header b/po/en@boldquot.header new file mode 100644 index 0000000..fedb6a0 --- /dev/null +++ b/po/en@boldquot.header @@ -0,0 +1,25 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# +# This catalog furthermore displays the text between the quotation marks in +# bold face, assuming the VT100/XTerm escape sequences. +# diff --git a/po/en@quot.header b/po/en@quot.header new file mode 100644 index 0000000..a9647fc --- /dev/null +++ b/po/en@quot.header @@ -0,0 +1,22 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# diff --git a/po/insert-header.sin b/po/insert-header.sin new file mode 100644 index 0000000..b26de01 --- /dev/null +++ b/po/insert-header.sin @@ -0,0 +1,23 @@ +# Sed script that inserts the file called HEADER before the header entry. +# +# At each occurrence of a line starting with "msgid ", we execute the following +# commands. At the first occurrence, insert the file. At the following +# occurrences, do nothing. The distinction between the first and the following +# occurrences is achieved by looking at the hold space. +/^msgid /{ +x +# Test if the hold space is empty. +s/m/m/ +ta +# Yes it was empty. First occurrence. Read the file. +r HEADER +# Output the file's contents by reading the next line. But don't lose the +# current line while doing this. +g +N +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/po/quot.sed b/po/quot.sed new file mode 100644 index 0000000..0122c46 --- /dev/null +++ b/po/quot.sed @@ -0,0 +1,6 @@ +s/"\([^"]*\)"/“\1”/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“”/""/g diff --git a/po/remove-potcdate.sin b/po/remove-potcdate.sin new file mode 100644 index 0000000..2436c49 --- /dev/null +++ b/po/remove-potcdate.sin @@ -0,0 +1,19 @@ +# Sed script that remove the POT-Creation-Date line in the header entry +# from a POT file. +# +# The distinction between the first and the following occurrences of the +# pattern is achieved by looking at the hold space. +/^"POT-Creation-Date: .*"$/{ +x +# Test if the hold space is empty. +s/P/P/ +ta +# Yes it was empty. First occurrence. Remove the line. +g +d +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/src/ChangeLog b/src/ChangeLog new file mode 100644 index 0000000..ee28ea6 --- /dev/null +++ b/src/ChangeLog @@ -0,0 +1,5206 @@ +2018-02-08 K. Handa + + Version 1.8.0 released. + + * m17n-core.h (M17NLIB_MINOR_VERSION): Changed to 8. + (M17NLIB_PATCH_LEVEL): Changed to 0. + (M17NLIB_VERSION_NAME): Changed "1.8.0". + +2017-12-09 handa + + * font.c (mfont__set_spec_from_plist): Fix for buffer overrun (bug + #50091). + +2017-12-08 handa + + * m17n-core.c (report_object_array): Check `objects' member + before freeing it. + (mdebug__register_object): Initialize `array' if `objects' member + is null. + + * internal.h (M17N_OBJECT_UNREF): Call m17n_object_unref if + MDEBUG_FINI is specified. + + * face.c (mface__init): Prepend a space to the name of Mface. + + * input.c (new_im_info): Add debug logging code. + (free_im_info): Likewise. + (minput__fini): Likewise. + +2016-02-28 handa + + * input.c (minput_parse_im_names): Fix a parsing bug of an input + methods name that omits the + language part. + +2015-11-13 Paul Eggert + + Fix buffer overruns in run_stages index array + + * m17n-flt.c (run_stages): Fix off-by-one bug in computing array + length; here, TO_POS is inclusive, not exclusive. + Also, do not overrun buffer if g_indices[len - 1] == -1. + +2015-08-29 K. Handa + + * internal-gui.h (MGlyph): New member libotf_positioning_type. + + * font-ft.c (ft_drive_otf): Define it for HAVE_OTF and not + HAVE_OTF separately. Adjusted for the new libotf functions + OTF_drive_gsub_features and OTF_drive_gpos_features. + +2015-08-29 Mike FABIAN + + * input.c (load_translation, filter): Fix type (int -> MSymbol). + +2015-04-05 K. Handa + + * m17n-flt.h (MFLTGlyph): Fix documentation. + +2014-12-10 K. Handa + + * Version 1.7.0 released. + +2014-11-11 K. Handa + + * .gitignore: Converted from .cvsigore. + + * .cvsignore: Delete it. + +2014-03-23 K. Handa + + * input.c (filter): Do not increment the reference count of + ic->produced. + +2014-03-12 K. Handa + + * m17n.h (minput_parse_im_names): Extern it. + + * mtext.c (insert): Preserve the tailing NULL. + + * input.c (create_ic_for_im): New argument `current'. Caller + changed. + (pop_im): Reset the pushed input method. + (filter): Update ic_info and im_info after popping and pushing. + +2014-03-07 K. Handa + + * input.c (prepare_fallback_input_methods): Use + minput_parse_im_names. + (re_init_ic): Do not save and restore ic_info->fallbacks. + (check_fallback): Check if map->submaps is NULL. + (minput_parse_im_names): New function. + + * plist.c (read_mtext_element): Be sure that the first argument to + read_mtext_element is null terminated. + +2014-02-09 K. Handa + + * internal.h (M17N_OBJECT_UNREF): Set an object having extended + count to NULL if it is freed. + +2014-02-09 K. Handa + + Changes to implement fallback input methods. + + * input.h (MIMInputStack): New type. + (MInputContextInfo): New members pushing_or_switching, fallbacks, + and stack. + + * input.c (MSwitch_im, Mpush_im, Mpop_im, Mfallback_input_method): + New variables. + (fallback_input_methods): New variables. + (prepare_fallback_input_methods): New function. + (fully_initialize): Initialize new variables. Call + prepare_fallback_input_methods at the end. + (parse_action_list): Recognize Mpush_im, Mpop_im, and Mswitch_im. + (create_ic_for_im): New function. + (check_variable_value): Recognize Mplits as type. + (take_action_list): Handle Mpush_im, Mpop_im, and Mswitch_im. + (handle_key): Propagate the return value of take_action_list to + the caller. Update the saved values of preedit text and cursor + position after running the init-actions of a state. + (struct MIMInputStack): New structure. + (pop_im, push_im): New funcitons. + (init_ic_info): Create contexts of fallback input methods. + (fini_ic_info): Free the above contexts. + (re_init_ic): Save and restore ic_info->fallbacks and + ic_info->stack. + (check_command_key): New function. + (check_reload): Call check_command_key. + (check_fallback): New function. + (filter): Handle push/pop input methods. + (minput__fini): Unref fallback_input_methods. + + * input-gui.c (win_filter): Restore ic->info to the original value + before calling "filter" driver. + +2013-10-28 Kenichi Handa + + * mtext.c (mtext_ref_char): Fix the logic. + +2012-12-15 Kenichi Handa + + * input.c [EXAMPLE_CODE] (get_im_command_description): Fix typo. + +2012-09-18 Kenichi Handa + + * Version 1.6.4 released. + +2012-09-17 Kenichi Handa + + * m17n-flt.c (run_stages): After removing separator glyphs, + re-check ctx->out->used. + +2012-04-23 Kenichi Handa + + * m17n-core.h (M17NLIB_PATCH_LEVEL): Changed to 4. + (M17NLIB_VERSION_NAME): Changed to "1.6.4" + +2012-03-21 Kenichi Handa + + * font-ft.c (fc_decode_prop): Fix for the case of too large VAL. + +2012-02-28 Kenichi Handa + + * m17n-core.h (M17NLIB_PATCH_LEVEL): Changed to 3. + (M17NLIB_VERSION_NAME): Changed to "1.6.3". + +2011-10-11 Kenichi Handa + + * Version 1.6.3 released. + +2011-09-12 Kenichi Handa + + * draw.c (analyse_bidi_level): Adjust a type (FriBidiParType). + +2011-06-19 Kenichi Handa + + * Makefile.am (libm17n_X_la_LIBADD): Add @FONTCONFIG_LD_FLAGS@. + +2011-03-09 Kenichi Handa + + * input.c (take_action_list): Move the handling of candidate-list + change to the function filter. + (filter): Adjusted as above. + +2011-02-14 Kenichi Handa + + * input.c (minput_list): Change the format of returning plist. + +2011-02-14 Kenichi Handa + + * m17n.h (minput_list): Extern it. + + * input.c (MIMExternalModule): New member 'name'. + (load_external_module): Return value changed. + (unload_external_module): New function. + (fini_im_info): Use unload_external_module. + (load_im_info): Adjuted for the change of load_external_module. + (minput_list): New function. + +2011-01-06 Kenichi Handa + + * coding.c: Fix comment syntax for doxygen. + +2010-12-13 Kenichi Handa + + * m17n-flt.c (mflt_enable_new_feature): Document it. + + * m17n-flt.h: Exclude extern variables from Doxygen's scope. + +2010-12-10 Kenichi Handa + + * m17n-flt.c (mflt_dump_gstring): Document it. + +2010-11-05 Kenichi Handa + + * locale.c (make_locale): Don't call setlocale. Just parse the + arg NAME. + +2010-10-04 Kenichi Handa + + * Version 1.6.2 released. + +2010-09-30 Kenichi Handa + + * input.c (open_im): Return -1 if the input method has no state. + +2010-09-17 Kenichi Handa + + * font-ft.c (ft_check_otf): Fix previous change. + +2010-09-16 Kenichi Handa + + * m17n-flt.c (parse_otf_command): Fix previous change. + +2010-09-14 Kenichi Handa + + * font-ft.c (ft_check_otf): Fix handling of negative features. + + * m17n-flt.c (parse_otf_command): Fix handling of negative + features. + (decode_packed_otf_tag): Fix updating category code. + (run_command): Fix `encoded' property of separator glyph. + (mflt_run): Improve debug info printing. + +2010-09-11 Kenichi Handa + + * src/charset.c, src/chartab.c, src/coding.c, src/face.c, + src/font.c, src/fontset.c, src/input.c, src/m17n-X.c, + src/m17n-core.c, src/m17n-flt.c, src/m17n-gd.c, src/m17n-gui.c, + src/m17n.c, src/mtext.c, src/plist.c, src/symbol.c, + src/textprop.c: Print debug information to mdebug__output instead + of stderr. + +2010-09-02 Kenichi Handa + + * draw.c (visual_order): Reorder only RTL composed-sequence. + +2010-09-01 Kenichi Handa + + * draw.c (compose_glyph_string): When the script `inherited' and + `common' can't be resolved, use "block" property of the character. + +2010-08-31 Kenichi Handa + + * draw.c (compose_glyph_string): Allow running flt striding over + the cursor position. + +2010-08-19 Kenichi Handa + + * m17n-X.c (MDisplayInfo): New member altgr_mask. + (find_modifier_bits): Set disp_info->altgr_mask. + + * input.c (fully_initialize): Make it static. + + * input.h (MINPUT_KEY_ALTGR_MODIFIER): New macro. + + * input-gui.c (minput_event_to_key): Handle + MINPUT_KEY_ALTGR_MODIFIER. + +2010-08-12 Kenichi Handa + + * character.h (STRING_CHAR_ADVANCE_UTF8): Sanitize the code. + (STRING_CHAR_ADVANCE_UTF16): Likewise. + + * font.c (mfont__init): Initialize buf to NULL. + (mfont__id): Likewise. + + * font-ft.c (ft_encapsulate): Use MDEBUG_PRINT1 instead of + MDEBUG_DUMP. + (ft_check_otf): Move the label not_otf: within #ifdef HAVE_OTF. + (get_otf): Move the code within #ifdef HAVE_OTF. + (ft_drive_otf): Move declarations of some local variables within + #ifdef HAVE_OTF. + +2010-08-11 Kenichi Handa + + * input.h (MInputContextInfo): New member state_hook. + + * input.c (shift_state): Just set ic_info->state_hook, instead of + taking state-hook actions. + (handle_key): Check ic_info->state_hook. If KEY is unhandled, + init ic_info->state_hook. + +2010-08-09 Kenichi Handa + + * m17n-flt.c (try_otf): Remove unused local vars. + + * input.c (fully_initialize): Avoid compiler warning by casting. + + * m17n-core.c (m17n_init_core): Fix handling of env_value. + + * fontset.c (realize_fontset_elements): Fix typo (pl->plist). + + * coding.c (decode_coding_iso_2022): Sanitize "if" condition. + +2010-04-23 Kenichi Handa + + * Version 1.6.1 released. + +2010-04-23 Kenichi Handa + + * m17n-flt.c (enum GlyphInfoMask): Shift upper masks 1-bit left. + (decode_packed_otf_tag): If a glyph has combining information, + don't touch it. + +2010-04-23 Kenichi Handa + + * font-ft.c (ft_drive_otf): Reset 28th bit of g->g.internal for + storing OTF feature tag. + +2010-04-19 Kenichi Handa + + * m17n-flt.c (run_stages): Update category code of glyphs if + category table is changed. + +2010-04-05 Kenichi Handa + + * font-ft.c (ft_check_cap_otf): Fix conditions to call + OTF_check_features. + + * database.c (check_version): Fix previous change. + +2010-04-02 Kenichi Handa + + * m17n-core.h (M17NLIB_MINOR_VERSION): Changed to 6. + (M17NLIB_PATCH_LEVEL): Changed to 1. + (M17NLIB_VERSION_NAME): Changed "1.6.1". + +2010-03-30 Kenichi Handa + + * Version 1.6.0 released. + +2010-03-01 Kenichi Handa + + * m17n-flt.c (run_rule): Fix checking of glyph availability. + +2010-02-18 Kenichi Handa + + * m17n-gui.c (register_device_library): Preprend M17N_MODULE_DIR + to the module file name. + + * input.c (load_external_module): Preprend M17N_MODULE_DIR to the + module file name. + + * charset.c (load_charset): Check the return value of fgets. + + * Makefile.am: Build modules dynamically loaded with + -avoid-version and no -version-info. + +2010-01-15 Kenichi Handa + + * draw.c (run_flt): Set mflt_try_otf to rfont->driver->try_otf. + (mdraw__init): Set mflt_enable_new_feature to 1. + + * font-ft.c (ft_try_otf): New function. + (mfont__ft_driver): Set ft_try_otf. + + * font.h (struct MFontDriver): New member try_otf. + + * m17n-X.c (xft_driver): Set xft_try_otf. + (xft_try_otf): New function. + + * m17n-flt.h: (mflt_enable_new_feature): Extern it. + (mflt_try_otf): Extern it. + + * m17n-flt.c (load_category_table): If mflt_enable_new_feature is + zero, return NULL for such categories that require the new + feature. + (parse_otf_command): If mflt_enable_new_feature is zero, return + -1. + (load_otf_command): Fix previous change. + (load_flt): Check the return value of load_category_table. + (try_otf): Renamed from run_otf_category. Call mflt_try_otf + instead of font->drive_otf. + (run_command): Call try_otf instead of run_otf_category. + (m17n_init_flt): Initialize mflt_enable_new_feature to 0, + mflt_try_otf to NULL. + (mflt_enable_new_feature): New variable. + (mflt_try_otf): New variable. + +2009-12-10 Kenichi Handa + + * m17n-flt.c (parse_otf_command): Handle ":otf?". + (run_otf_category): If not features are specified, reset category + codes. + (run_command): On copy, don't re-calculate a category code. + +2009-12-03 Kenichi Handa + + * m17n-flt.c (run_stages): Reset category code if category-table + is changed. + (mflt_run): Don't set category code here. + (decode_packed_otf_tag): If no feature is applied, re-calculate + category code. + +2009-12-02 Kenichi Handa + + * m17n-flt.c (mflt_find): If FONT is specified but no flt is + found, return NULL. + (run_command): Don't set ENCODED and MEASURED of separator. + +2009-11-30 Kenichi Handa + + * m17n-flt.c (load_otf_command): Check 4th char against '?'. + (load_command): Likewise. + (decode_packed_otf_tag): New arg CTX. If CTX->in == gstring, + update CTX->encoded. Caller changed. + +2009-11-30 Kenichi Handa + + * font-ft.c (ft_drive_otf): Check if OUT is null or not. + (ft_drive_otf): Call OTF_drive_gsub_with_log and + OTF_drive_gpos_with_log. Record the applied feature in + g->g.internal. + + * font.c (mfont__get_glyph_id): Encode g->c instead of g->code. + + * internal-flt.h (MAKE_COMBINING_CODE_BY_CLASS) + (COMBINING_BY_CLASS_P, COMBINING_CODE_CLASS) + (MAKE_PRECOMPUTED_COMBINDING_CODE, COMBINING_PRECOMPUTED_P): + Delete externs.. + (PACK_OTF_TAG): Extern it. + + * draw.c (reorder_combining_chars): Delete it. + + * m17n-flt.h (mflt_font_id): Use type MFLFont. + (mflt_iterate_otf_feature): Likewise. + + * m17n-flt.c (enum GlyphInfoMask): New member CategoryCodeMask and + CombinedMask. + (GET_CATEGORY_CODE, SET_CATEGORY_CODE, GET_COMBINED): New macros. + (SET_COMBINING_CODE): Set also CombinedMask. + (FontLayoutFeatureTable): Delete it. + (FeatureCodeTable): New type. + (FontLayoutCategory): Type of feature_table changed. + (load_category_table): Adjusted for the change of + FontLayoutCategory. + (unref_category_table): Likewise. + (gen_otf_tag): New member shift. Caller changed. + (FontLayoutContext): New member category. + (run_rule): Compare g->c instead of g->code. + (decode_packed_otf_tag): New function. + (run_otf): Call decode_packed_otf_tag. Don't reset combining-code + here. + (run_otf_category): New function. + (run_command): Set category-code if necessary. Call + run_otf_category for FontLayoutCmdTypeOTFCategory. + (run_stages): Set ctx->category. Get category from glyph if + possible. + (mflt_dump_gstring): New function. + +2009-11-26 Kenichi Handa + + * m17n-flt.c (enum FontLayoutCmdType): New member + FontLayoutCmdTypeOTFCategory. + (FontLayoutFeatureTable): New type. + (FontLayoutCategory): New members feature_table_size and + feature_table. + (load_category_table): Handle feature_table. + (unref_category_table): Likewise. + (load_otf_command): Handle FontLayoutCmdTypeOTFCategory. + (load_command): Likewise. + (free_flt_command): Likewise. + +2009-11-10 Kenichi Handa + + * draw.c (run_flt): Update category code of each glyph. + +2009-11-07 Kenichi Handa + + * font-ft.c (ft_drive_otf): Don't accumulate anchor adjustments. + +2009-11-05 Kenichi Handa + + * m17n-flt.c (run_otf): Fix updating of g->lbearing, etc. + + * font-ft.c (ft_drive_otf): Use OTF_drive_gpos2 if possible. + +2009-10-28 Kenichi Handa + + * fontset.c (mdebug_flag): New variable. + (mfont__lookup_fontset): Print debug info. + + * m17n-core.c (m17n_init_core): Call SET_DEBUG_FLAG for + MDEBUG_FONTSET. + + * internal.h (enum MDebugFlag): Add MDEBUG_FONTSET. + + * language.c (mscript__from_otf_tag): Adjusted for the new format + of the database . + +2009-10-22 Kenichi Handa + + * database.c (check_version): Fix the check. + + * input.c (surrounding_pos): New arg *pos. + (integer_value): Fix handling of "@+0". + (take_action_list): Adjusted for the change of surrounding_pos. + +2009-10-05 Kenichi Handa + + * m17n-flt.h: (mflt_iterate_otf_feature, mflt_font_id): Extern + them. + + * m17n-flt.c (FontLayoutCategory): New typedef. + (FontLayoutStage): Type of the member `category' changed. + (struct _MFLT): Type of the member `coverage' changed. New member + need_config and font_id. + (apply_otf_feature): New function. + (load_category_table): New arg FONT. If FONT is non-NULL, call + apply_otf_feature. Setup category->definition. + (ref_category_table): New macro. + (unref_category_table): New function. + (load_flt): Adjusted for the type change of category. + (free_flt_stage): New arg FLT. + (list_flt): Adjusted for the type change of category. + (run_stages): Adjusted for the type change of category. + (configure_category, configure_flt): New function. + (m17n_init_flt): Initialize mflt_iterate_otf_feature and + mflt_font_id to NULL. + (mflt_get): Skip the heading configured FLTs. + (mflt_find): Likewise. If necessary, configure the found flt. + (mflt_run): Handle mflt_iterate_otf_feature and mflt_font_id. + Adjusted for the type change of category. + (mflt_iterate_otf_feature, mflt_font_id): New variable. + + * m17n-X.c (xfont_open): Set rfont->id. + (xft_driver): Set xft_iterate_otf_feature. + (xft_open): Set rfont->id. + (xft_iterate_otf_feature): New function. + + * font.h (struct MRealizedFont): New member id. + (struct MFontDriver): New member iterate_otf_feature. + + * font.c (mfont__get_glyph_id): Pay attention to. mfont->source. + + * font-ft.c (ft_open, ft_encapsulate): Set rfont->id. + (get_otf): New funcition. + (ft_check_otf, ft_drive_otf): Use get_otf. + (iterate_callback, ft_iterate_otf_feature): New functions. + (mfont__ft_driver): Set ft_iterate_otf_feature. + + * draw.c: Docstring updated. + (font_id): New function. + (run_flt): Set mflt_font_id and mflt_iterate_otf_feature before + calling mflt_run. + +2009-10-02 Kenichi Handa + + * m17n-flt.c (load_flt): Check the return value of + load_category_table. + +2009-09-03 Kenichi Handa + + * m17n-flt.c (run_otf): Clear combining code for glyphs whose + positions are adjusted by GPOS table. + +2009-08-13 Kenichi Handa + + * Version 1.5.5 released. + +2009-08-13 Kenichi Handa + + * m17n-core.h (M17NLIB_PATCH_LEVEL): Changed to 5. + (M17NLIB_VERSION_NAME): Changed to "1.5.5". + +2009-03-03 Kenichi Handa + + * draw.c (compose_glyph_string): Check if category not Mnil. + +2009-03-02 Kenichi Handa + + * Version 1.5.4 released. + +2009-02-25 Kenichi Handa + + * m17n-core.c (report_object_array): For M-text and Plist, print + more information. + + * m17n-core.h (M17NLIB_PATCH_LEVEL): Changed to 4. + (M17NLIB_VERSION_NAME): Changed to "1.5.4". + + * input.c (get_candidate_list): Free unnecessary objects. + (take_action_list): Free plist. + +2009-02-04 Kenichi Handa + + * coding.c (mcoding__init): Add "Shift_JIS" as an alias of "sjis". + +2009-01-16 Kenichi Handa + + * m17n-core.h (Mcased, Msoft_dotted, Mcase_mapping, Mblock): + Extern them. + + * character.c (Mcased, Msoft_dotted, Mcase_mapping, Mblock): New + variables. + +2009-01-14 Kenichi Handa + + * coding.c (decode_coding_iso_2022): Check invocation status + before updating charset0 and charset1. + + * symbol.c (msymbol__canonicalize): Handle "windows-XXXX". + +2008-12-31 Kenichi Handa + + * m17n-flt.c (mflt_run): If g->encoded is set, don't clear + g->code. + +2008-10-30 Andreas Schwab (tiny change) + + * face.c (mface_get_prop): Fix strict aliasing bug. + (mface_put_prop): Likewise. + + * m17n-gui.c (mframe): Fix strict aliasing bug. + +2008-10-20 Kenichi Handa + + * Version 1.5.3 released. + +2008-10-06 Kenichi Handa + + * draw.c (mdraw__init): Use TRUE only when + FRIBIDI_INTERFACE_VERSION is less than 3. + +2008-10-03 Kenichi Handa + + * database.c (mdatabase__find_file): Return a copy of filename if + it is absolute pathname. + +2008-09-25 Kenichi Handa + + * input.c (load_macros): Don't parse the action list here. + (load_im_info): Parse action lists of all macros. + +2008-09-24 Kenichi Handa + + * m17n-flt.c (mflt_find): Setup coverage of "combining" flt. + +2008-09-19 Kenichi Handa + + * input.c (fully_initialize): Rename "@reload" to "-reload". + +2008-09-17 Kenichi Handa + + * m17n-flt.c (run_stages): Fix combining with a variable width + font. + +2008-08-04 Kenichi Handa + + * input.c (fully_initialize): Add more aliaese (e.g. C-M-1 + vs. C-A-1). + +2008-07-22 Kenichi Handa + + * input.c (fully_initialize): Fix previous change. + +2008-07-19 Kenichi Handa + + * input.c (fully_initialize): Fix previous change. + +2008-07-14 Kenichi Handa + + * font-ft.c (ft_list_family): New arg CHECK_ALIAS. Callers changed. + +2008-07-14 Kenichi Handa + + * input.c (fully_initialize): Handle C-M-1, etc. + +2008-07-11 Kenichi Handa + + * input.c (minput_open_im): Check if the arg NAME is not Mnil. + +2008-06-23 Kenichi Handa + + * Version 1.5.2 released. + +2008-06-23 Kenichi Handa + + * m17n-core.h (M17NLIB_MINOR_VERSION): Changed to 5. + (M17NLIB_PATCH_LEVEL): Changed to 2. + (M17NLIB_VERSION_NAME): Changed "1.5.2". + +2008-06-13 Kenichi Handa + + * input.c (minput_config_file): Comment fixed for man-page. + +2008-06-13 Harshula (tiny change) + + * Makefile.am (libm17n_gd_la_LIBADD): Add @FREETYPE_LD_FLAGS@. + +2008-05-24 Kenichi Handa + + * m17n-flt.c (mdebug_dump_flt): Change return value to (MFLT *). + +2008-05-23 Kenichi Handa + + * Makefile.am (libm17n_gui_la_LIBADD): Include libm17n-core.la. + (libm17n_X_la_LIBADD): Include libm17n-core.la, libm17n.la, and + libm17n-flt.la. + (libm17n_gd_la_LIBADD): Likewise. + + * input.c (take_action_list): Fix debug info. + +2008-05-14 Kenichi Handa + + * m17n-flt.c (run_rule): Check SRC_REGEX at first. + (run_stages): Fix index of g_indices. + +2008-04-03 Kenichi Handa + + * draw.c (compose_glyph_string): Don't run flt striding over the + cursor position. + (get_gstring): Don't use the cached gstring if cursor position is + changed. + +2008-04-02 Kenichi Handa + + * input.c (integer_value): Delete the 3rd arg VALUE. + (resolve_expression): Adjust the call of integer_value. + (take_action_list): Likewise. + +2008-03-06 Kenichi Handa + + * font-ft.c (ft_drive_otf): Don't ignore the otf-spec to apply all + features. + +2008-01-31 Kenichi Handa + + * Version 1.5.1 released. + +2008-01-31 Kenichi Handa + + * draw.c (mdraw_glyph_list): Refer to mfont__ft_driver only when + HAVE_FREETYPE is defined. + + * font.h (OTF_Tag): Be sure that it is defined in any cases. + +2008-01-30 Kenichi Handa + + * font.h (enum MFontOpenTypeTable, MFontCapability): Define them + unconditionally. + +2008-01-25 Kenichi Handa + + * input.c (parse_action_list): Handle the case "(insert INTEGER)". + +2008-01-25 Kenichi Handa + + * input.c (parse_action_list): Check M_candidates. + (get_im_info): If key is Mnil, be sure to set im_info->states to a + plist. + +2008-01-23 Kenichi Handa + + * input.c (integer_value): Fix interpretation of "@-N". + +2008-01-17 Kenichi Handa + + * input.c (get_following_char): Fix interpretation of POS. + (get_following_char): Fix interpretation of "@+N". + +2008-01-15 Kenichi Handa + + * font-ft.c (ft_drive_otf): Don't refer to otf_gstring if HAVE_OTF + is not defined. + + * Makefile.am (FLT_SOURCES): Include internal-flt.h. + +2008-01-07 Kenichi Handa + + * m17n-flt.c (UPDATE_CLUSTER_RANGE): Don't check if clustering + now. + (run_rule): Call UPDATE_CLUSTER_RANGE when necessary. + (run_command): Check if clustering now before calling + UPDATE_CLUSTER_RANGE. + +2008-01-06 Kenichi Handa + + * font.c (mfont__get_glyph_id): Return -1 if some code is invalid. + + * font-ft.c (ft_drive_otf): Fix checking of negative feature. + + * m17n-X.c (xft_find_metric): Set g->g.measured. + + * m17n-flt.c (Mequal): New variable. + (m17n_init_flt): Initialize it. + (FontLayoutCmdRule): Merge members supported_glyph and otf_spec + into a new member facility. + (load_command): Modify parsing of Mfont_facility. + (run_rule): Adjuted for the change of FontLayoutCmdRule. + (run_otf): Adjusted metrics if a->back is nonzero. + +2007-12-28 Kenichi Handa + + * Version 1.5.0 released. + +2007-12-13 Kenichi Handa + + * m17n-core.c (m17n_init_core): Handle the lang. env. MDEBUG_FLT. + + * m17n-flt.c (mdebug_flag): Set to MDEBUG_FLT. + (run_rule): Check if a font has the specific glyph correctly. + + * internal.h (enum MDebugFlag): Delete MDEBUG_FONT_OTF, change + MDEBUG_FONT_FLT to MDEBUG_FLT. + + * font.c (mfont__get_glyph_id): Encode g->g.code (not g->g.c). + + * font-flt.c: Delete it. + +2007-12-08 Kenichi Handa + + * m17n-flt.c (run_rule): Fix printing of debug info. Don't update + TO for the rule of SRC_HAS_GLYPH. + + * draw.c (run_flt): Argument changed. + (compose_glyph_string): Adjusted for the above change. + +2007-12-07 Kenichi Handa + + * plist.c (read_mtext_element): Don't free the malloced buffer. + +2007-12-04 Kenichi Handa + + * m17n-core.h (merror_code): Extern it. + + * m17n-misc.h (merror_code): Don't extern it. + + * m17n.h: Handle the case of _M17N_FLT_H_ being defined. + + * m17n-flt.h: Handle the case of _M17N_H_ being defined. + +2007-11-22 Kenichi Handa + + * draw.c (compose_glyph_string): Check g->rface->layouter, not + g->rface->rfont->layouter. + + * font-ft.c (ft_drive_otf): Fix setting of g->g.from and g->g.to. + + * m17n-flt.c (FontLayoutContext): New member encoded_offset. + (run_rule): Use ctx->encoded_offset. + (run_command): Likewise. + (run_stages): Set ctx->encoded_offset. + +2007-11-21 Kenichi Handa + + * m17n-flt.c (enum GlyphInfoMask): Adjusted for the change of + bit-size of MFLTGlyph->internal. + +2007-11-20 Kenichi Handa + + * draw.c (visual_order): Exclude the last anchor glyph from the + iteration. + + * m17n-flt.h (MFLTGlyph): New member . + + * m17n-flt.c (run_otf): Set adjusted flag of glyphs if necessary. + (run_stages): Likewise. + (load_flt): Unref top after checking plist. + + * m17n-X.c (xft_render): Check adjusted flag of glyphs. + +2007-11-12 Kenichi Handa + + * font-ft.c (ft_check_otf): Fix arg to OTF_check_features. + + * m17n-flt.c (Mcombining): New variable. + (Mfont_facility): Renamed from Mfont_has. Referrer changed. + (enum FontLayoutCmdRuleSrcType): Delete SRC_EXIST, add + SRC_HAS_GLYPH and SRC_OTF_SPEC. + (FontLayoutCmdRule): Delete src.exist, add src.supported_glyph and + src.otf_spec. + (load_command): Adjusted for the above changes. + (run_rule): Likewise. + (combining_code_from_class): Delete it. + (mflt_get): Check flt->name against Mcombining, not Mt. + + * internal-flt.h (Mcombining): Extern it. + + * draw.c (compose_glyph_string): Call run_flt with Mcombining for + combining characters. + +2007-11-09 Kenichi Handa + + * face.c (mface__realize): Reset measured flag before calling + mfont__get_metric. + + * m17n-flt.c (run_stages): Fix handing of off_x and off_y. + (setup_combining_coverage): New function. + (setup_combining_flt): New function. + (mflt_get): If flt is not found, return NULL. If name if Mt, + call setup_combining_flt. + (mflt_run): For debugging, print font family name. + + * font-ft.c (ft_render): Fix handling of baseline_offset. + (ft_encapsulate): Set metrics in 26.6 fixed pixel. + (ft_render): Check pixel_mode to determine anti_alias. + + * m17n-X.c (xfont_find_metric): Delete invalid "continue" line. + (xfont_find_metric): Set metrics in 26.6 fixed pixel. + (xfont_render): Set baseline_offset in pixel. + (xft_render): Fix handling of baseline_offset. + + * draw.c (run_flt): Set font.font.family. + (compose_glyph_string): Fix handling of combining characters. + + * fontset.c (try_font_list): Check if the named flt is surely + available. + +2007-11-07 Kenichi Handa + + * draw.c (analyse_bidi_level): New function. + (visual_order): Do reordering using the already decided + bidi-level. + (compose_glyph_string): Decide bidi-level before calling flt. + + * m17n-flt.c (mflt_run): Fix typo. + + * font-ft.c (ft_drive_otf): Fix indexing gstring->glyphs. + +2007-11-06 Kenichi Handa + + * draw.c (visual_order): Don't rely on the width of glyphs. + (run_flt): Fix culculation of g->g.to. + + * m17n-flt.c (run_rule): Don't set error code here. + (run_cond): Likewise. + (run_otf): Fix culculation of xoff and yoff. + (run_command): Don't set error code here. + (PREV): New macro. + (NEXT): New macro. + + * m17n-X.c (xfont_open): Keep rfont's metrics in 26.6 fixed pixels. + (xfont_find_metric): Set glyph's yadv to 0. + (xft_find_metric): Likewise. + + * font-ft.c (ft_open): Keep rfont's metrics in 26.6 fixed pixels. + (ft_find_metric): Adjust glyph's metrics. + (ft_encapsulate): Keep rfont's metrics in 26.6 fixed pixels. + (ft_drive_otf): Set mark glyph's xadv to 0. + + * face.c (mface__for_chars): Adjusts the unit of face's ascent and + descent. + +2007-10-29 Kenichi Handa + + * m17n-flt.h (struct _MFLTOtfSpec): Adjusted for the new FLT handling. + (mflt_get): Adjusted for the argument change. + (mflt_name): Adjusted for the return value change. + + * m17n-flt.c (Mgenerator, Mend): New variables. + (flt_min_coverage, flt_max_coverage): New variables. + (GCPY): New macro. + (GDUP): Use it. + (Mfont_has): Renamed from Mexist. Referrers chagned. + (gen_otf_tag): Handle the trailing whitespaces. + (otf_count_features, otf_store_features): Fix for negative features. + (parse_otf_command): Adjusted for the change of MFLTOtfSpec. + (load_otf_command): Likewise. + (free_flt_command): Adjusted for the change of MFLTOtfSpec. + (load_flt): Argument changed. Caller changed. + (free_flt_list): New function. + (run_rule): Adjusted for the change of FontLayoutContext. + (mflt_run): Adjusted for the change of FontLayoutContext. + + * m17n-gui.c (m17n_init_win): Call m17n_init_flt. + (m17n_fini_win): Call m17n_fini_flt. + + * m17n-gui.h: Include m17n-flt.h. + + * m17n-gd.c: Adusted for the change of MGlyph. + + * m17n-X.c: Adusted for the change of MGlyph. + (xft_check_otf, xft_drive_otf): New functions. + + * internal-gui.h (MGlyph): Modified for new FLT handling. + + * fontset.c (try_font_list): Adusted for the change of MGlyph. + + * font-ft.c: Adjusted for the change of MGlyph. + (ft_check_cap_otf): Renamed from ft_check_otf. Callers changed. + (get_glyph_metric): Deleted. + (ft_check_otf): New function. + (ft_drive_otf): New fucntion. + + * font.c: Adjusted for the change of MGlyph. + (mfont__init): Don't call mfont__flt_init. + (mfont__fini): Don't call mfont__flt_fini. + (mfont__get_glyph_id, mfont__get_metrics): New functions. + + * font.h (struct MRealizedFont): New members x_ppem and y_ppem. + (MFLTFontForRealized): New struct. + (struct MFontDriver): New members check_otf and drive_otf. + (mfont__get_glyph_id, mfont__get_metrics): Extern them. + + * face.c: Adjusted for the change of MGlyph. + + * draw.c: Adjusted for the change of MGlyph. + + * m17n.c (m17n_init): Don't call mchar_init. + + * m17n-core.c (m17n_init_core): Call mchar_init. + + * m17n-core.h (mchartable_min_char, mchartable_max_char): Extern them. + + * input.c: Include "m17n.h" instead of "m17n-gui.h". + + * chartab.c (mchartable): Initialize table->min_char to -1. + (mchartable_min_char): New function. + (mchartable_max_char): New function. + + * Makefile.am (GUI_SOURCES): Delete font-flt.c. + (libm17n_gui_la_LIBADD): Add ${top_builddir}/src/libm17n-flt.la. + +2007-10-12 Kenichi Handa + + * m17n-core.h (Mcharset): Extern it. + Move detabase related declarations from m17n.h. + + * m17n-flt.h: Include m17n-core.h instead of m17n.h. + (struct _MFLTOtfFeatures): New struct. + (struct _MFLTOtfSpec): Delete gsub, gpos, etc, add gsub_gpos. + (struct _MFLTFont): Delete otf, add check_otf. + (MCHAR_INVALID_CODE): Define it. + + * plist.c (read_mtext_element): Simplify the code. + + * m17n.h: Move database related declarations to m17n-core.h + (Mharset): Don't extern it. + + * m17n.c (m17n_init): Don't call mdatabase__init. + + * m17n-gd.c (read_rgb_txt): Check also /etc/X11/rgb.txt. Downcase + color names. + + * m17n-flt.c: Include m17n-core.h instead of m17n.h. + (Mexist): New variable. + (enum FontLayoutCmdRuleSrcType): New enum SRC_EXIST. + (FontLayoutCmdRule): New member src.exist. + (parse_otf_command): Handle gsub_count and gpos_count separately. + (load_otf_command): Adjusted for the change of MFLTOtfSpec. + (load_command): Handle the command "exist". + (free_flt_command): Adjusted for the change of MFLTOtfSpec. + (run_rule): Handle the case SRC_EXIST. + (run_otf): Adjusted for the change of MFLTOtfSpec. + (run_command): Check the range of FROM. + (check_otf_spec): Delete it. + (m17n_init_flt): Call m17n_init_core instead of m17n_init. + Initialize Mexist. + (m17n_fini_flt): Call m17n_fini_core instead of m17n_fiini. + (mflt_find): Call font->check_otf instead of check_otf_spec. + (mflt_run): Keep the metrics in 26.6 fixed point. + + * m17n-core.c (mdatabase__finder, mdatabase__loader): Delete them. + (m17n_init_core): Call mdatabase__init. + + * m17n-X.c (device_open): Use mplist_add, not mplist_push. + + * internal.h (mdatabase__finder, mdatabase__loader): Delete externs + of them. + + * font-flt.c (Mexist): New variable. + (enum FontLayoutCmdRuleSrcType): New enum SRC_EXIST. + (FontLayoutCmdRule): New member src.exist. + (load_category_table): Use isalnum, not isalpha. + (load_command): Check the command "exist". + (run_rule): Hande the case SRC_EXIST. + (run_command): Check the range of FROM. + (mfont__flt_init): Initialize Mexist. + + * draw.c (layout_glyphs): Fix calculation of off_x and off_y. + + * database.h (mdatabase__load_charset_func): Extern it. + + * database.c: Include m17n-core.h instead of m17n.h. + (load_chartable): Use mtext__from_data. + (load_charset): Moved to charset.c + (load_database): Call mdatabase__load_charset_func instead of + load_charset. + (mdatabase__load_charset_func): New variable. + (mdatabase__init): Initialize mdatabase__load_charset_func and + Mcharset. Don't set mdatabase__finder and mdatabase__loader. + (mdatabase__save): Use fwrite, not mconv_encode_stream. + (Mcharset): Declare it here. + + * charset.c: Include "database.h.". + (load_charset): Moved from database.c. + (mcharset__init): Initialize mdatabase__load_charset_func, don't + initialize Mcharset. + + * character.c (mchar_define_property): Call mdatabase_find directly. + (mchar_get_prop): Call mdatabase_add directly. + (mchar_put_prop): Call mdatabase_load directly. + (mchar_get_prop_table): Likewise. + + * Makefile.am (libm17n_core_la_SOURCES): Add database.[ch]. + (libm17n_la_SOURCES): Remove database.[ch]. + (libm17n_flt_la_LIBADD): Delete libm17n.la, add libm17n-core.la. + +2007-09-18 Kenichi Handa + + * face.c (mface__realize): Try Freetype based font at first. + + * font.c: Include + +2007-09-16 Kenichi Handa + + * m17n-flt.c (load_flt): New arg full. If full is zero, load only + coverage. + (run_otf): Call font->get_metrics, not font->get_metric. + (run_stages): Likewise. + (CHECK_FLT_COVERAGE): New macro. + (CHECK_FLT_STAGES): Call load_flt with the second arg 1. + (check_otf_spec): New function. + (m17n_fini_flt): Unref flt->coverage. + (mflt_find): Argument changed. + (mflt_name): New function. + (mflt_coverage): Use CHECK_FLT_COVERAGE. + + * m17n-flt.h (MFLTFont): Member get_metrics renamed from get_metric. + (mflt_find): Prototype adjusted. + (mflt_name): Extern it. + +2007-09-14 Kenichi Handa + + * m17n-flt.h (struct _MFLTGlyph): Change signedness of members. + + * font-flt.c (run_otf): Make debug info printing comaptible with + that of m17n-flt.c. + (run_command): Likewise. + (mfont__flt_run): Likewise. + + * m17n-flt.c (UPDATE_CLUSTER_RANGE): ctx->cluster_begin_idx is + invalid only when it's negative. + (run_otf): Likewise. + (run_command): Likewise. + (mflt_run): Initialize ctx.cluster_begin_idx to -1. + +2007-09-10 Kenichi Handa + + * m17n-flt.h (struct _MFLTGlyph): New member encoded and measured. + (struct _MFLTFont): Prototype of get_glyph_id changed. + + * m17n-flt.c (enum GlyphInfoMask): Delete EncodedMask and + PositionedMask. + (GAPPEND): Delete this macro. + (GET_ENCODED, SET_ENCODED, GET_MEASURED, SET_MEASURED): Adjusted + for the change of MFLTGlyph. Caller changed. + (run_otf): Simply calls font->get_glyph_id. + (run_command): Reset g->encoded and g->measured for direct code. + (positioning): Delete this function. + (run_stages): Simply calls font->get_glyph_id and font->get_metric. + +2007-09-07 Kenichi Handa + + * draw.c (compose_glyph_string): Improve script detection. + +2007-09-06 Kenichi Handa + + * m17n-flt.h (mflt_get): Extern it. + + * m17n-flt.c (run_stages): Call positioning only if + font->get_metric is non-NULL. + (CHECK_FLT_STAGES): Fix typo. + (mflt_get): New function. + + * font-flt.c (mfont__flt_run): Improve debug info printing. + +2007-09-04 Kenichi Handa + + * m17n-flt.c (MFontLayoutTable): Delete this type. + (struct _MFLT): New member mdb and coverage. + (list_flt): Set flt->mdb. + (load_generator): Argument and return value changed. Caller + changed. + (get_font_layout_table): Delete this function. + (run_stages): Argument changed. Caller changed. + (CHECK_FLT_STAGES): New macro. + (mfont__flt_encode_char): Argument changed. + (mflt_find): Likewise. + (mflt_coverage): New function. + (mflt_run): Argument changed. + (mdebug_dump_flt): Likewise. + + * m17n-flt.h (mflt_coverage): Extern it. + (mflt_find): Prototype adjusted. + +2007-09-03 Kenichi Handa + + * internal.h (MTABLE_CALLOC_SAFE, MSTRUCT_CALLOC_SAFE): New macros. + + * database.c (mdatabase__props): New function. + + * database.h (mdatabase__props): Extern it. + + * m17n-flt.h (struct _MFLTGlyphString): Delete user_data, add + script and langsys. + (struct _MFLTFont): Add suitable_p. + (mflt_find): Extern it. + + * m17n-flt.c: Include "database.h". + (struct _MFLT): New struct. + (list_flt): New function. + (load_flt): Don't update flt_list. + (get_font_layout_table): Use flt_list. + (m17n_init_flt): Don't initialize flt_list. + (m17n_fini_flt): Adjusted for the change of flt_list. + (mflt_find): New function. + (mflt_run): Fix debug printing. + +2007-08-23 Kenichi Handa + + * m17n-flt.c (run_otf): Remove #ifdef HAVE_OTF and #endi. + (run_stages): Print separator in encoded string as "|". + +2007-08-23 Kenichi Handa + + * font-flt.c (mfont__flt_run): Don't calculate a glyph metric if + the glyph is already handled by OTF. + +2007-08-21 Kenichi Handa + + * font-ft.c (ft_check_capability): Check cap->script_tag at first. + +2007-08-20 Kenichi Handa + + * font-flt.c (mfont__flt_run): Get glyph metrics before printing + debug information. + +2007-08-17 Kenichi Handa + + * m17n-flt.h (struct _MFLTGlyphString): Member pointer renamed to + user_data. + (MFLTOtfSpec): Renamed from MFLT_OTF_Spec. + (MFLTFont): Prototype of the member drive_otf adjusted. + + * m17n-flt.c (run_stages): Fix handling of padding. + + * font-ft.c (get_glyph_metric): New function. + (DEVICE_DELTA): Return 26.6 fixed point value. + (adjust_anchor): Likewise. + (mfont__ft_drive_otf): Use get_glyph_metric. + + * font-flt.c (mfont__flt_run): Pay attention to padding on + printing debug info. + +2007-08-16 Kenichi Handa + + * m17n-flt.c (run_stages): Fix typo. + + * font-ft.c (adjust_anchor): Argument changed. Calculte based on + 26.6 fixed point. + (mfont__ft_drive_otf): Don't call OTF_check_features for GPOS. + Adjusted for the argument change of adjust_anchor. Calculte based + on 26.6 fixed point. + +2007-08-15 Kenichi Handa + + * charset.c (mcharset__load_from_database): Set mdebug_flag + instead of mdebug_mask. + + * coding.c (mcoding__load_from_database): Set mdebug_flag instead + of mdebug_mask. + + * database.c (load_database): Set mdebug_flag instead of + mdebug_mask. + (mdatabase__load_for_keys): Likewise. + + * draw.c: Include "internal-flt.h". + (dump_combining_code): Don't subtract 128 from combining code + off_x/y. + + * font-flt.c: Include "internal-flt.h". Set mdebug_flag instead + of mdebug_mask. + (run_rule): Print debug info only when MDEBUG_FLAG is greater than + 2. + (run_cond): Likewise. + (run_otf): Likewise. + (run_command): Likewise. + (mfont__flt_run): Change format of debug info. + + * font-ft.c: Include "internal-flt.h". + Set mdebug_flag instead of mdebug_mask. + (mfont__ft_drive_otf): Fix arg to OTF_check_features. + + * input.c: Set mdebug_flag instead of mdebug_mask. + (shift_state): New MDEBUG_FLAG macro. + (preedit_commit): Likewise. + (filter): Likewise. + + * internal-flt.h: New file. + + * internal-gui.h (MAKE_COMBINING_CODE, COMBINING_CODE_OFF_Y) + (COMBINING_CODE_OFF_X, COMBINING_CODE_BASE_X) + (COMBINING_CODE_BASE_Y, COMBINING_CODE_ADD_X) + (COMBINING_CODE_ADD_Y, MAKE_COMBINING_CODE_BY_CLASS) + (COMBINING_BY_CLASS_P, COMBINING_CODE_CLASS) + (MAKE_PRECOMPUTED_COMBINDING_CODE, COMBINING_PRECOMPUTED_P): Move + these macros to internal-flt.h. + + * internal.h (M17N_OBJECT_ADD_ARRAY): Adjusted for the change of + mdebug__flags. + (M17N_OBJECT_REGISTER, M17N_OBJECT_UNREGISTER): Likewise. + (enum MDebugMaskBit): Delete this enum. + (enum MDebugFlag): New enum. + (mdebug__flag): Don't extern it. + (mdebug__flags): Extern it. + (MDEBUG_FLAG): New macro. + (MDEBUG_PRINT0): Use the macro MDEBUG_FLAG. + (MDEBUG_DUMP, MDEBUG_PUSH_TIME, MDEBUG_POP_TIME) + (MDEBUG_PRINT_TIME): Likewise. + + * m17n-X.c (xfont_open): Set mdebug_flag instead of mdebug_mask. + (xfont_list): Likewise. + + * m17n-core.c (mdebug__flag): Delete this variable. + (mdebug__flags): New variable. + (SET_DEBUG_FLAG): Make it a function. + (m17n_init_core): Set mdebug_flag instead of mdebug_mask. + (m17n_fini_core): Likewise. + + * m17n-gui.c (m17n_init_win): Set mdebug_flag instead of mdebug_mask. + (m17n_fini_win): Likewise. + + * m17n-misc.h (enum MErrorCode): Add MERROR_FLT. + + * m17n.c (m17n_init): Set mdebug_flag instead of mdebug_mask. + (m17n_fini): Likewise. + + * symbol.c (msymbol__free_table): Adjusted for the change of + mdebug__flags. + + * Makefile.am (BASICBUILDS): Add libm17n-flt.la. + (BASICHEADERS): Add m17n-flt.h. + (FLT_SOURCES): New variable. + (libm17n_flt_la_SOURCES, libm17n_flt_la_LIBADD) + (libm17n_flt_la_LDFLAGS): Likewise. + + * m17n-flt.h: New file. + + * m17n-flt.c: New file created by modifying font-flt.c. + +2007-07-13 Kenichi Handa + + * Version 1.4.0 released. + +2007-07-12 Kenichi Handa + + * input.c: Fix doxygen @ref commands. + +2007-07-10 Kenichi Handa + + * m17n-core.h (M17NFunc): Fix typo of Doxygen directive. + +2007-07-09 Kenichi Handa + + * m17n-core.h (M17N_BEGIN_HEADER, M17N_END_HEADER): New macros. + + * m17n.h: Include m17n-core.h if not yet done. Use macros + M17N_BEGIN_HEADER and M17N_END_HEADER. + + * m17n-gui.h: Likewise. + + * m17n-misc.h: Likewise. + +2007-06-13 Kenichi Handa + + * font-flt.c (load_command): Prepend "^" in the regular expression. + +2007-06-11 Kenichi Handa + + * language.c (mlanguage_name_list): Fix previous change. + + * coding.c (mcoding__load_from_database): Add aliases in + coding_definition_list. + +2007-06-10 Kenichi Handa + + * language.c (mlanguage_name_list): Fix previous change. + +2007-06-08 Kenichi Handa + + * input.c (update_candidate): Copy candidate_list earlier. + (re_init_ic): Provide pseudo initialize state if none. + +2007-06-05 Kenichi Handa + + * input.c (preedit_insert): Print debug information. + + * database.c (expand_wildcard_database): New function. + (mdatabase_list): Fix handling of wildcard database. + + * language.c (load_lang_name): New function. + (mlang__fini): Cancel the last two changes. + (mlanguage_name_list): New arg script and territories. Use + load_lang_name. + + * m17n.h (mlanguage_name_list): Adjusted. + +2007-06-04 Kenichi Handa + + * input.c (open_im): Check if the input method has at least one + state. + +2007-06-01 Kenichi Handa + + * input.c (shift_state): Change the format of debug print. + (preedit_commit): New arg need_prefix. Caller changed. + (update_candidate): Copy candidate_list. + (take_action_list): Likewise. + (handle_key): Change the format of debug print. + + * font-flt.c (load_flt): Ignore unknown directives. + +2007-05-25 Kenichi Handa + + * m17n-core.c (mdebug__unregister_object): Small optimization. + + * database.c (find_file): Merged into get_database_file. + (get_database_file): New arg result. Caller changed. + (mdatabase__check): Fix the logic. + +2007-05-24 Kenichi Handa + + * database.c (find_database): If unprocessed wildcard database is + found, register database filed and recursively call find_database. + (free_db_info): Unref db_info->properties. + (register_database): New arg properties. Delete code for + initializing mdatabase__list. + (register_databases_in_files): Argument changed. Caller changed. + (mdatabase__update): Don't list files by glob here. + (mdatabase_list): If unprocessed wildcard database is found, + register database filed and recursively call mdatabase_list. + + * database.h (enum MDatabaseStatus): New enum + MDB_STATUS_AUTO_WILDCARD. + + * input.c (load_branch): Fix previous change. + (update_global_info): If the global database is not found, return -1. + +2007-05-23 Kenichi Handa + + * database.c (Mversion): New variable. + (mdatabase__init): Initialize it. + (register_database): New arg properties. Caller changed. + (register_databases_in_files): Don't check version here. + (mdatabase__update): Likewise. + + * database.h (MDatabaseInfo): New member properties. + +2007-05-21 Kenichi Handa + + * language.c: Include + (mlanguage__info): Use strncasecmp (not memcmp). + (mlanguage_name): Downcase language name for backward + compatibility. + + * input.c (filter): Don't check Mlanguage property of + ic->im->language. + +2007-05-18 Kenichi Handa + + * language.c (mlanguage_name): Fix it to handle M-text English + name. + + * input.c (config_command): Set NAME before using it. + (load_branch): Try to resolve a map name by variables. + +2007-05-17 Kenichi Handa + + * language.c (mlang__fini): Fix previous change. + +2007-05-16 Kenichi Handa + + * plist.c (free_plist): Cancel the last change. + (write_element): Check if PLIST is nested. + (mplist__from_plist): Label a plist as nested if appropriate. + (mplist__from_alist): Label a plist as nested. + (mplist__conc): Check the value of PL before referring it. Label + a plist as nested if appropriate. + (mplist_copy): Label a plist as nested if appropriate. + (mplist_put_func): Return Mnil if KEY is a managing key. + (mplist_push): Label a plist as nested if appropriate. + + * plist.h (MPLIST_SET_NESTED_P): Return 1 iff plist->control.flag + is set as nested. + + * language.c (mlang__fini): Unref each element of langname_list. + +2007-05-14 Kenichi Handa + + * language.c: Include and . + (langname_list): New variable. + (load_lang_script_list): Exclude invalid list elements. + (mlang__init): Initialize langname_list. + (mlang__fini): Unref langname_list. + (mlanguage__info): Adjusted for the change of English + name (symbol->M-text). + (mlanguage_name): Label it as obsolete. + (mlanguage_name_list): New function. + + * m17n.h (mlanguage_name_list): Extern it. + + * locale.c (make_locale): Fix setting of members of locale. + + * plist.c (free_plist): Unref also nested plist. + +2007-05-11 Kenichi Handa + + * coding.c (mconv_reset_converter): Set internal->used to 0. + +2007-05-08 Kenichi Handa + + * input.c (check_description): Force copying the translated text. + +2007-05-02 Kenichi Handa + + * input.c (minput_save_config): Unref unnecessary plist. Use + free_im_list to free im_config_list. + +2007-04-20 Kenichi Handa + + * input.c (config_command): Fix previous change again. + (config_variable): Likewise. + (minput_config_command): Fix for the case of setting back to + default. + (minput_config_variable): Likewise. + (minput_save_config): Include nil as documentation of customized + command/variable. + +2007-04-05 Kenichi Handa + + * input.c (config_command): Fix previous change. + (config_variable): Likewise. + + * plist.c (mplist_get_func): Fix for backward compatiblity. + +2007-04-04 Kenichi Handa + + * input.c (minput_get_command, minput_config_command): Fix example + codes. + +2007-03-29 Kenichi Handa + + These changes are to avoid unsafe casting of a function pointer. + + * face.h (enum MFaceProperty): Delete MFACE_HOOK_FUNC. + (struct MFace): New member hook. + + * face.c (serialize_face): Adjusted for the change of MFace. + (deserialize_face): Likewise. + (mface__init): Likewise. Use msymbol_put_func. + (mface__realize): Adjusted for the change of MFace. Avoid + compiler warning. + (mface_get_prop): Adjusted for the change of MFace. + (mface_put_prop): Likewise. + (mface_get_hook): New function. + (mface_put_hook): New function. + (mface_update): Adjusted for the change of MFace. + + * input-gui.c (win_callback): Use mplsit_get_func. + (minput__win_init): Use mplsit_put_func. + + * input.c (take_action_list): Use mplist_get_func. + (init_ic_info): Likewise. + (fini_ic_info): Likewise. + (minput_callback): Likewise. + (minput__init): Use mplist_put_func. + + * language.c (mlang__init): Use msymbol_put_func. + + * m17n-core.h (M17NFunc): New function type. + (M17N_FUNC): New macro. + (msymbol_put_func, msymbol_get_func): Extern them. + (mplist_put_func, mplist_get_func): Extern them. + + * m17n-gui.h (mface_get_hook, mface_put_hook): Extern them. + + * m17n-gui.c (mframe): Add a proper casting. + + * plist.h (struct MPlist): Make the member val a union. + (MPLIST_VAL): Adjusted for the above change. + (MPLIST_FUNC): New macro. + (MPLIST_VAL_FUNC_P, MPLIST_SET_VAL_FUNC_P): New macros. + + * plist.c (mplist_put_func, mplist_get_func): New functions. + + * symbol.c (msymbol__fini): Use MPLIST_VAL. + (msymbol_put_func, msymbol_get_func): New functions. + + * textprop.c (mtext_serialize): Use msymbol_get_func. + (mtext_deserialize): Likewise. + +2007-03-28 Kenichi Handa + + * input.c (get_candidate_list): Avoid unnecessary unref. + +2007-03-23 Kenichi Handa + + * database.c (mdatabase__update): Unref plist at the tail. + +2007-03-21 Kenichi Handa + + * input.c (update_custom_info): Fix for the case "name == Mnil && + extra != Mnil". + (config_command): Fix for the case that configuration is + cancelled. + (config_variable): Likewise. + (minput_config_command): If keyseqlist is an empty list, cancel + the customization. + (minput_config_variable) If value is an empty list, cancel the + customization. + (minput_save_config): Handle cancellation of config and customize + correctly. + +2007-03-15 Kenichi Handa + + * input.c (minput_config_variable): Check custom->vars (not + custom->cmds). + +2007-03-01 Kenichi Handa + + * input.c (reload_im_info): Setup cmds, vars, and title of + im_info. + (check_variable_value): Fix the return value. + + * database.c (mdatabase__check): If necessary, update database and + find a new file. + +2007-02-28 Kenichi Handa + + * database.c (get_dir_info): Set dir_info->status to + MDB_STATUS_OUTDATED. + (check_version): New function. + (register_database): Don't call find_database. + (register_databases_in_files): Don't register a database of + invalid version. + (mdatabase__update): Likewise. Avoid unnecessary scanning. + + * database.h (enum MDatabaseStatus): New membes MDB_STATUS_UPDATED + and MDB_STATUS_OUTDATED. + + * font.h (struct MFont): Types of members type, source, and + spacing changed to unsigned. + + * internal-gui.h (struct): Types of members category and type + changed to unsigned. + + * internal.h (struct MText): Types of members format and coverage + changed to unsigned. + + * m17n-core.h (M17NLIB_PATCH_LEVEL): Changed to 5. + (M17NLIB_VERSION_NAME): Changed to "1.3.5". + +2007-02-23 Kenichi Handa + + * input.c (Mpop): New variable. + (fully_initialize): Initialize Mpop. + (parse_action_list): Handle Mpop. + (take_action_list): Likewise. + (handle_key): When a key is unhandled, shift to the initial state + only if the current state has no branch action. + +2007-02-12 Kenichi Handa + + * input.c (get_preceding_char): Unref mt if necessary. + (get_following_char): Likewise. + (parse_action_list): Fix handling of `insert' action as + candidates. + (get_candidate_list): Fix for handling (("CANDIDATE1" ...)). + (take_action_list): Check invalid candidate list. + +2007-02-06 Kenichi Handa + + * input.c (integer_value): Check also ic->produced for @-N. + +2007-01-26 Kenichi Handa + + * database.c (mdatabase__update): Check mdatabase__dir_list from + the tail. + + * font-ft.c (STRDUP_LOWER): Don't ignore the tailing spaces. + +2007-01-12 Kenichi Handa + + * input.c (handle_key): Handle a branch action of the initial + state correctly. + +2007-01-10 Kenichi Handa + + * m17n-gd.c (gd_render): Delete superfluous line. + +2006-12-26 Kenichi Handa + + * m17n.h (minput_callback): Extern it. + + * input.h (minput__callback): Delte extern. + + * input.c (get_surrounding_text): Adjusted for the change of + minput__callback to minput_callback. + (delete_surrounding_text): Likewise. + (minput_create_ic): Likewise. + (minput_destroy_ic): Likewise. + (minput_filter): Likewise. + (minput_set_spot): Likewise. + (minput_toggle): Likewise. + (minput_reset_ic): Likewise. + + (preedit_commit): Reset ic->candidate_index, ic->candidate_from, + and ic->candidate_to to 0. + (minput_callback): Renamed from minput__callback. + + * input-gui.c (win_callback): Adjusted for the change of + minput__callback to minput_callback. + +2006-12-15 Kenichi Handa + + * font-ft.c (ft_add_font): Fix typo. + +2006-12-06 Kenichi Handa + + * Version 1.3.4 released. + +2006-11-16 Kenichi Handa + + * input.c (parse_action_list): Allow (undo 0). + (adjust_markers): New function. + (preedit_insert, preedit_delete): Call adjust_markers. + (preedit_replace): New function. + (update_candidate): Call preedit_replace instead of preedit_insert + and preedit_delete. + (filter): When ic_info->commit_key_head is nonzero, shift input + event keys even if there's no committed text. + +2006-11-10 Kenichi Handa + + * input.h (MInputContextInfo): New member commit_key_head. + + * input.c (preedit_commit): Update ic_info->commit_key_head. + (take_action_list): Reset ic_info->commit_key_head on Mundo. + (filter): When committed, shift keys by ic_info->commit_key_head. + +2006-10-30 Kenichi Handa + + * input.c (preedit_delete): Fix typo. + (take_action_list): Print more debugging information. Allow + variable in arg of 'select' and `pushback'. + + * database.c (gen_database_name): Don't put extra space. + (load_database): Print debugging information. + (register_databases_in_files): New arg headlen. Callers changed. + (mdatabase__load_for_keys): Shorten debugging information. + (mdatabase_load): Don't print debugging information here. + +2006-10-27 Kenichi Handa + + * input.c (marker_code): New arg surrounding. Callers changed. + (surrounding_pos): Check if name[0] == '@'. + (integer_value): Fix for the change semantics of `@-N' and `@+N'. + (take_action_list): Likewise. + (get_preceding_char): If POS is zero, always call + get_surrounding_text. + +2006-10-19 Kenichi Handa + + * input.c (load_variables): Fix setting of `global'. + +2006-10-16 Kenichi Handa + + * draw.c (draw_background): Be sure to set *to_x. + (render_glyph_string): If from == to, just return. + +2006-10-18 Kenichi Handa + + * database.c (get_dir_info): Return NULL if the directory name is + too long. + (register_databases_in_files): Call register_database with + MDB_STATUS_AUTO. + (mdatabase__update): Fix logic. Call register_database with + MDB_STATUS_AUTO. + (mdatabase_define): Call register_database with + MDB_STATUS_EXPLICIT. + + * input.c (delete_surrounding_text): Be sure to set members + preceding_text and following_text to NULL. + (shift_state): Save variable values in ic_info->vars_saved. + (preedit_commit): Don't print debug information here. Don't + change ic_info->keys here. + (get_candidate_list): Don't ref plist. + (take_action_list): Don't unref return value of + get_candidate_list. For undo, reset ic->produced and recover + ic_info->vars. Be sure to set ic->candidate_list to NULL after + unref it. + (init_ic_info): Set ic_info->vars_saved. + (fini_ic_info): Unref ic_info->vars_saved. + (re_init_ic): Be sure to set ic->candidate_list to NULL after + unref it. + (filter): Be sure to set members preceding_text and following_text + to NULL. Print debug information about produced text. Delete + processed keys from ic_info->keys. + + * input.h (MInputContextInfo): New member vars_saved. + +2006-10-16 Kenichi Handa + + * database.c (mdatabase__update): Fix the way to get db_info. + +2006-10-02 Kenichi Handa + + * font.h (struct MFont): New member `multiple_sizes'. Bit-size of + `size' changed to 24. + + * font.c (xlfd_unparse_name): Adjusted for the change of + MFont->size. + (font_score): Likewise. + (mfont__set_spec_from_face): Set spec->multiple_sizes to 0. + + * m17n-X.c (MFontX, _MFontX): Deleted. + (SET_SIZE, HAVE_SIZE): Deleted. + (free_display_info): Adjusted for the change of + disp_info->font_list format. + (xfont_registry_list): Likewise. + (xfont_open): Likewise. + (xfont_list): Likewise. + (xfont_encode_char): Ignore size to find a realized font. + (MRealizedFontXft): Change the order of members to make it + compatible with MRealizedFontFT. + +2006-09-27 Kenichi Handa + + * font.c (mfont_match_p, mfont_open, mfont_encapsulate) + (mfont_close): Add comments. + + * mtext-lbrk.c (mtext_line_break): Add comment. + +2006-09-26 Kenichi Handa + + * input.c (minput_get_description): Handle description about + inclusion-only input methods. + +2006-09-21 Kenichi Handa + + * input.c (M_gettext): New variable. + (fully_initialize): Initialize M_gettext. + (check_description): New function. + (load_commands): Call check_description. + (config_all_commands): Be sure to unref pl. + (load_variables): Call check_description. + (config_all_variables): Be sure to unref pl. + (load_im_info): Call check_description. + + * internal.h [ENABLE_NLS]: Include and define _. + + * m17n-core.c (m17n_init_core) [ENABLE_NLS]: Call bindtextdoman + and bind_textdomain_codeset. + + * Makefile.am (AM_CPPFLAGS): Add -DGETTEXTDIR=... + +2006-09-15 Kenichi Handa + + * input.c (reload_im_info): Update custom and global info. + (init_ic_info): Fix previous change. + +2006-09-14 Kenichi Handa + + * database.c: Include . + (mdatabase__lock): Make a directory if necessary. + + * input.c (resolve_command): Adjusted for the format change of + configured_cmds member. + (load_commands, load_variables): Fix for errornous data handling. + (config_command, config_variable): New function. + (config_all_commands, config_all_variables): Renamed from + config_commands and config_variables. Utilize the above function. + (check_variable_value): Argument changed. Callers changed. + (load_im_info): Call config_all_commands and config_all_variables. + (init_ic_info): Adjusted for the format change of configured_vars + member. + (minput__init): Initialize Mcustomized, Mconfigured, and + Minherited. + (Mcustomized, Mconfigured, Minherited): New variables. + (minput_get_command): Be sure to return NULL if an input method + use no local command. + (minput_get_variable): Be sure to return NULL if an input method + use no local variable. + (minput_config_command, minput_config_variable) + (minput_save_config): Adjusted for the format change of + configured_cmds and configured_vars members. + + * plist.c (write_element): Delete superfluous ':'. + +2006-09-13 Kenichi Handa + + * m17n.h (Minherited, Mcustomized, Mconfigured): Extern them. + (minput_config_file): Extern it. + + * draw.c (Minherited): Declaration moved to input.c. + (mdraw__init): Don't initialize Minherited here. + + * database.c (mdatabase__unlock): Be sure to unlink uniq file. + +2006-09-07 Kenichi Handa + + * textprop.c (mtext_serialize): Call mplist__serialize with the + arg pretty 0. + + * plist.h (mplist__serialize): Prototype adjusted. + (mplist__assq): Extern it. + + * plist.c: Include + (PUTC, PUTS): New macros. + (write_symbol): New function. + (write_element): New arg indent. + (dump_string, dump_plist_element): Delete them. + (mplist__from_string): New arg pretty. + (mplist__assq): New function. + (mdebug_dump_plist): Use write_element. + + * mtext.c (mtext_cat_char): Allocate more memory. + (mdebug_dump_mtext): Don't escal a newline character. + + * m17n.h (minput_get_command, minput_get_variable) + (minput_config_command, minput_config_variable) + (minput_save_config): Extern them. + + * m17n-core.c: Include . + (m17n_init_core): If the env. var. MDEBUG_OUTPUT_FILE is "stdout", + use the stream stdout instead of a file of that name. + + * m17n-X.c (mwin__parse_event): Fix handling of Shift and Control + modifiers. + + * internal.h (MFAILP, MDEBUG_PRINT0): New macros. + (MDEBUG_PRINT, MDEBUG_PRINT1, MDEBUG_PRINT2, MDEBUG_PRINT3) + (MDEBUG_PRINT4, MDEBUG_PRINT5): Use MDEBUG_PRINT0. + (MDEBUG_DUMP): Flush the stream. + + * input.h (struct _MInputMethodInfo): Delete member im. New + members mdb, language, name, extra, cmds, configured_cmds, + bc_cmds, vars, configured_vars, bc_vars, description, and tick. + (MInputContextInfo): New member tick. + + * input.c: Big change to improve user-side input method + customization. Here, list just public API changes. + (minput_get_commands, minput_get_variables) + (minput_assign_command_keys, minput_set_variable): Label them + obsolete. + (minput_get_command, minput_get_variable) + (minput_config_command, minput_config_variable) + (minput_save_config): New functions. + + * database.h (PATH_MAX): Define it if not yet defined. + (PATH_SEPARATOR): Likewise. + (enum MDatabaseStatus): New enum. + (struct MDatabaseInfo): Moved from database.c. New members status, + time, lock_file, and uniq_file. + (mdatabase__update, mdatabase__file, mdatabase__lock, mdatabase__save) + (mdatabase__unlock): Extern them. + + * database.c: Include . + (MDB_DIR_LEN): Don't include the terminating '\0' in the length. + (GEN_PATH): Args changed. Callers changed. + (struct MDatabaseInfo): Moved to database.h. + (struct MDatabase, mdb_list): Deleted. + (mdatabase__list): New var. + (get_database_filename): Deleted. Callers changed to use + get_database_file. + (find_file, get_database_file): New files. + (get_dir_info): Initialize new members of MDatabaseInfo. + (find_database): Arg chagnded. Callers changed. + (free_db_info, register_database, register_databases_in_files): + New functions. + (update_database_list): Deleted. + (mdatabase__init): Initialize mdatabase__list instead of mdb_list. + (mdatabase__fini): Finalize mdatabase__list instead of mdb_list. + (mdatabase__update): New function. + (mdatabase__check): Return value changed. + (mdatabase__file, mdatabase__lock, mdatabase__save) + (mdatabase__unlock): New functions. + +2006-08-30 TAKAHASHI Naoto + + * input.c (get_surrounding_text): Return -2 when surrounding text + is unavailable. + (get_following_char): Likewise. + (get_preceding_char): Likewise. + (minput__callback): Return 0 if there is a callback function, + otherwise -1. + +2006-08-17 Kenichi Handa + + * input.c (reset_ic): Use shift_state to setup the current state. + +2006-08-02 Theppitak Karoonboonyanan (tiny change) + + * Makefile.am (libm17n_la_LIBADD, libm17n_gui_la_LIBADD) + (libm17n_X_la_LIBADD, libm17n_gd_la_LIBADD, linkcore_LDADD) + (linkshell_LDADD, linkgui_LDADD): Use ${top_builddir}. + +2006-08-02 Kenichi Handa + + * plist.c (mdebug_dump_plist): Fix the 2nd arg to dump_plist_element. + + * mtext.c (mdebug_dump_mtext): If not fullp, dump just text. + + * font-ft.c (ft_encapsulate): Add code for debugging. + (mfont__ft_drive_otf): Be sure to encode character before getting + metrics. + +2006-07-21 Kenichi Handa + + * draw.c (mdraw_text_extents): Fix previous typo. + +2006-07-19 Kenichi Handa + + * draw.c (gstring_width): New arg lbearing. + (render_glyph_string): Adjusted for the change of gstring_width. + (mdraw_text_extents): Fix lbearing of ink and line metrics. + + * m17n-core.h (Mlanguage): Extern it. + + * m17n.h (Mlanguage): Extern deleted. + + * mtext.c (mtext__init): Initialize Mlanguage. + (Mlanguage): Declaration moved from locale.c + + * locale.c (mlocale__init): Don't initialize Mlanguage here. + (Mlanguage): Declaration moved to mtext.c. + + * language.c (mlang__init): Don't initialize Mlanguage here. + + * font.c (OTF_tag_name) [! HAVE_OTF]: New function. + +2006-07-14 Kenichi Handa + + * font-ft.c: Use FT_BDF_H macro. Include fontconfig/fcfreetype.h. + (MRealizedFontFT): New member face_encapsulated. + (free_ft_rfont): Pay attention to ft_rfont->face_encapsulated. + (ft_gen_font): New function. + (ft_add_font): Use ft_gen_font. + (ft_list_script): Store lists in ft_script_list. + (ft_check_otf): New arg ft_face. Caller changed. + (ft_check_language): Likewise. + (ft_check_script): Likewise. + (ft_encapsulate, ft_close): New functions. + (mfont__ft_driver): Initialize members encapsulate and close. + (mfont__ft_drive_otf): Use OTF_open_ft_face if it is available. + + * font.h (struct MRealizedFont): New member encapsulating. + (struct MFontDriver): New members encapsulate and close. + + * font.c (mfont__match_p): If FONT is realized, check capability + by font drivers's check_capability method. + (mfont_match_p, mfont_open, mfont_encapsulate, mfont_close): New + functions. + + * m17n-X.c (xfont_list_family_names): Delete unused var. Fix + declarations of foundry and fam local vars. + (xft_driver): Make it static. + + * m17n-gui.h (mfont_match_p, mfont_open, mfont_encapsulate) + (mfont_close): Extern them. + + * m17n-gd.c (device_open): Don't specify foundry and family of the + default face. + +2006-07-11 Kenichi Handa + + * m17n-gui.c (m17n_fini_win): Set null_interface.handle to NULL; + +2006-07-13 Kenichi Handa + + * font-ft.c (fc_build_charset): Return NULL if FcCharSet can't be + created. + (ft_check_script): Delete unused var. + (ft_list_capability): Likewise. + + * font.c (mfont__get_capability): Setup cap->otf. + (Motf): Make it global. + (mfont_get_prop): Accept Mlanguage, Mscript, and Motf as key arg. + + * font.h (MFontCapability): New member otf. + + * language.c (mlang__fini): Delete unused vars. + + * m17n-gui.h (Motf): Extern it. + + * database.c (update_database_list): Delete unused vars. + +2006-07-07 Kenichi Handa + + * font-ft.c (DEVICE_DELTA): Fix typo. + +2006-07-06 Kenichi Handa + + * fontset.c (mfont__lookup_fontset): Don't ignore family and + foundry of face. + +2006-07-05 TAKAHASHI Naoto + + * database.c: Update comments. + +2006-07-05 Kenichi Handa + + * database.c (PATH_MAX): Define it if not yet defined. + (PATH_SEPARATOR, USE_GEN_PATH, GEN_PATH, GEN_PATH_FROM_MT): New + macros. + (get_database_filename): Use GEN_PATH. + (get_dir_info): Don't include the last '/' in directory name. + (register_database): New function. + (update_database_list): Use register_database. Search all + directories in mdatabase__dir_list for wildcard databases. + (mdatabase__init): Check "~/.m17n.d". + +2006-07-03 Kenichi Handa + + * input-gui.c (win_callback): If is ic->candidate_show zero, don't + push reverse property. + + * plist.c (dump_plist_element): Fix previous change. + +2006-06-28 Kenichi Handa + + * font.c (xlfd_unparse_name): Suppress the heading '-' if not + necessary. + + * draw.c (MbidiNSM): New variable. + (visual_order) [! HAVE_FRIBIDI]: Clear levels at first. Pay + attention to bidi type NSM. + (mdraw__init): Initialize MbibiNSM. + + * language.c (mscript__char_list): Fix finding a char-list element. + + * plist.c (dump_string): Return number of printed characters. + (dump_plist_element): Print elements more compactly. + +2006-06-23 Kenichi Handa + + * Makefile.am (BUILD_LIBS): Don't increment it conditionally. + (include_HEADERS): Likewise. + +2006-06-23 TAKAHASHI Naoto + + * language.c: Update documentation. + +2006-06-23 Kenichi Handa + + * font-ft.c (struct MFontFT): Delete member lang. + (free_ft_info): Don't unref member lang. Destroy members langset + and charset. + (fc_parse_pattern): Last argument changed to MFontFT *. Callers + changed. Set members langset and charset. + (fc_init_font_list, fc_list_pattern, fc_build_charset): New + functions. + (ft_init_font_list, ft_has_char_list_p, ft_list_char_list): New + functions. + (ft_list_family) [HAVE_FONTCONFIG]: Include FC_CHARSET on objset. + (ft_list_family) [! HAVE_FONTCONFIG]: Call ft_init_font_list. + (ft_list_language) [HAVE_FONTCONFIG]: Check representative + characters at first. If it fails, try listing by language names. + (ft_list_language) [! HAVE_FONTCONFIG]: Call ft_list_char_list. + (ft_check_language): Renamed from ft_check_lang. Adjusted for the + change of MFontCapability. + (ft_list_capability): Likewise. Try listing by languages, then by + scripts. Check OTF at last. + (ft_check_script): New function. + (ft_select): Adjusted for the check of MFontCapability. + (ft_list_family_names): New function. + (ft_check_capability): If cap->script is not Mnil, call + ft_check_script. + (mfont__ft_driver): Initialize with ft_list_family_names. + + * font.h (struct MFontDriver): New member list_fmaily_names. + (struct): Change member "MSymbol *lang" to "MSymbol language". + + * font.c: Include "language.h". + (Motf): New variable. + (otf_script_list, load_otf_script_list): Delete it. + (find_script_from_otf_tag): Delete it. + (merge_capability): New function. + (mfont__init): Init Motf. + (mfont__fini): Don't unref otf_script_list. + (free_font_capability): Check cap->script_tag to determine if + OTF-related capability is set. + (mfont__get_capability): Call mscript__from_otf_tag. Adjusted for + the change of type MFontCapability. + (mfont_put_prop): Call merge_capability for Mlanguage, Mscript, + and Motf properties. + (mfont_list): Call merge_capability for LANGUAGE arg. + (mfont_list_family_names): New function. + + * input-gui.c: Typo in comments fixed. + + * input.c: Typo in comments fixed. + + * language.h (mlanguage__list): Delete it. + (mscript__char_list, mscript__otf_tag, mscript__from_otf_tag): New + functions. + + * language.c: Include "mtext.h". + (M_script_lang_list): Delete it. + (language_list, script_list): New variables. + (load_lang_script_list, init_language_list, init_script_list): New + functions. + (mlang__init): Don't load language database here. + (mlang__fini): Unref language_list and script_list if not NULL. + (mlanguage__list): Delete it. + (mlanguage__info, mscript__info, mscript__char_list) + (mscript__otf_tag, mscript__from_otf_tag): New functions. + (mlanguage_list, mlanguage_code, mlanguage_name, mlanguage_text) + (mscript_list, mscript_language_list): New functions. + + * m17n-gui.h (mfont_list_family_names): Extern it. + + * m17n.h (mlanguage_list, mlanguage_code, mlanguage_name) + (mlanguage_text, mscript_list, mscript_language_list): Extern + them. + +2006-06-21 Kenichi Handa + + * m17n-X.c (xfont_driver): Initialize with + xfont_list_family_names. + (xfont_list_family_names): New function. + (xft_driver): Initialize with NULL for list_family_names member. + (device_init): Set list_family_names member of xft_driver to that + of mfont__ft_driver. + +2006-06-06 Kenichi Handa + + * fontset.c (mfont__lookup_fontset): Don't set *num to 1 if it is 0. + +2006-03-24 Kenichi Handa + + * font-ft.c (ft_open): Improve debug message. + + * fontset.c (mfontset__get_font): Fix for the case that no font in + per_script list is available. + +2006-02-06 Kenichi Handa + + * Version 1.3.3 released. + +2006-02-22 Kenichi Handa + + * textprop.c: Fix some typos in documentation. + + * plist.c: Fix some typos in documentation. + + * m17n-core.h: Fix some typos in documentation. + (M17NLIB_PATCH_LEVEL): Updated to 3. + (M17NLIB_VERSION_NAME): Updated to "1.3.3". + + * symbol.c: Fix some typos in documentation. + + * mtext.c: Fix some typos in documentation. + + * input.c: Fix several typos in documentation. + +2006-02-06 Kenichi Handa + + * Version 1.3.2 released. + +2006-02-03 Kenichi Handa + + * m17n-core.h (M17NLIB_PATCH_LEVEL): Updated to 2. + (M17NLIB_VERSION_NAME): Updated to "1.3.2". + + * font.c (xlfd_parse_name): Fix handling of the name "nil". + + * draw.c (layout_glyphs): Fix handling left_padding of + composition's base. + + * m17n-gd.c (read_rgb_txt): Support HTML 4.0 color names. + +2006-02-02 Kenichi Handa + + * Makefile.am (include_HEADERS): Add m17n-gui.h and m17n-X.h only + if WITH_GUI is true. + +2006-01-25 Kenichi Handa + + * input.c (resolve_expression): If the value of PLIST is a plist, + but the first element is not symbol, return 0. + +2006-01-17 Kenichi Handa + + * m17n-gd.c (gd_render): Use gdImageColorResolveAlpha only if + HAVE_GD is 2 or the greater. + +2006-01-16 Kenichi Handa + + * Version 1.3.1 released. + +2006-01-16 Kenichi Handa + + * m17n-gd.c (gd_render): Use gdImageColorResolveAlpha instead of + simulating anti-aliasing. + + * m17n-core.h (M17NLIB_PATCH_LEVEL): Updated to 1. + (M17NLIB_VERSION_NAME): Updated to "1.3.1". + +2006-01-12 Kenichi Handa + + * input.c (get_surrounding_text): Always pop ic->plist. + (reset_ic): Don't reset ic->plist. + +2006-01-10 Kenichi Handa + + * input.c (preedit_commit): For debugging, print only commiting + charactes. Don't set ic->candidate_show to 0. + (handle_key): Don't run branch-actions just by shifting to the + current state. + (reset_ic): Reset state_key_head and key_head of ic_info to 0. + Reset vars and plist. + +2006-01-07 Kenichi Handa + + * input.c (load_branch): Confirm that maps is not NULL. + +2006-01-05 Kenichi Handa + + * input-gui.c (win_filter): Try to convert arg to key only when + arg is not NULL. + + * plist.c (read_integer_element): If '#' and '-' are followed by + non-integer-constituent, read them as a part of a symbol. + (read_symbol_element): New arg C. + (read_element): Adjust args to read_symbol_element. + + * input.c (load_macros): On overwriting a macro, free the old + definition. + (minput__init): Store Mmap in load_im_info_keys. + (minput_get_title_icon): If the input method has no title, be sure + to return NULL. + (minput_get_description): If the input method has no description, + be sure to return NULL. + (minput_get_variables): Fix documentation. + (handle_key): Pay attention to the case that key is Mnil. + (filter): Likewise. Fix handling of such symbol as S-A. + +2005-12-22 Kenichi Handa + + * Version 1.3.0 released. + +2005-12-22 Kenichi Handa + + * font-ft.c (ft_list): If the specified font has no property, + return all fonts. + +2005-12-20 Kenichi Handa + + * character.c (mchar_get_prop): Check char_prop_list. + (mchar_put_prop, mchar_get_prop_table): Likewise. + +2005-12-18 Kenichi Handa + + * input.c (minput_get_title_icon): If LANGUAGE is Mt, try also a + file name sans language. + +2005-12-16 TAKAHASHI Naoto + + * input.c: Fix typo in comments. + +2005-12-14 Kenichi Handa + + * input.c (minput_get_title_icon): Check the default icon for the + input method. + +2005-12-13 Kenichi Handa + + * input.c (Mless_equal, Mgreater_equal): New variables. + (parse_expression, resolve_expression, parse_action_list) + (take_action_list): Handle the aboves. + (filter): Treat key S-X as X. + (minput__init): Initialize Mless_equal and Mgreater_equal. + (minput_get_title_icon): New function. + + * m17n.h (minput_get_title_icon): Extern it. + + * database.c (get_database_filename): Return a filename instead of + file pointer. + (load_database): Adjusted for the above change. + (mdatabase__load_for_keys): Likewise. + (mdatabase__find_file): New function. + + * database.h (mdatabase__find_file): Extern it. + + * font.h (mfont__resize): Delete extern. + + * font.c (mfont__list): Check resize ratio. + (mfont__resize): Delete it. + (mfont_resize_ratio): Include the code of mfont__resize. + + * font-ft.c (ft_open): Check resize ratio. + + * m17n-X.c (xfont_open): Check resize ratio. + (xft_open): Likewise. + +2005-12-07 Kenichi Handa + + * input.c (take_action_list): If take_action_list return -1, + return -1. + (handle_key): Likewise. + + * face.c (mface__for_chars): When font is specified and layouter + is found for it, if the layouter doesn't support one of a + character, use a face sans layouter for it. + +2005-12-06 Kenichi Handa + + * fontset.c (mfont__lookup_fontset): If only a fallback font is + found, don't use it for more than one character. + +2005-12-05 Kenichi Handa + + * face.c (mface__realize): Set rfont->layouter to Mnil. + (mface__for_chars): Fix handling of layouter. + + * character.h (mchar__define_prop): Extern it. + + * database.c (update_database_list): Call mchar__define_prop if + necessary. + + * character.c (mchar__init): Don't call mchar_define_property. + Instead just initialize property keys. + (mchar__fini): Free char_prop_list only if it's not NULL. + (mchar__define_prop): New function. + (mchar_define_property): Call mchar__define_prop. + + * m17n-core.c (m17n_fini_core): Call mtext__prop_fini at after + mplist__fini. + +2005-12-02 Kenichi Handa + + * language.c (mlang__init): Handle extra chars. + + * m17n-gui.h (mfont_check): Adjust prototype. + + * m17n-X.c (xfont_driver): Specify xfont_check_capability. + (xfont_check_capability): New function. + (xft_driver): Specify xft_check_capability. + (xft_check_capability): New function. + + * font-ft.c (M0_3): Delete it. + (M0): New variable. + (ft_get_charmaps): Refer to M0. + (fc_parse_pattern): Fix previous change. + (ft_list_language): Check also extra chars. + (ft_check_otf): Define it even if HAVE_OTF is undef. + (ft_check_lang): Check the result of FcLangSetHasLang against + FcLangDifferentLang. Check also extra chars. + (ft_list_capability): Delete ifdef HAVE_OTF. + (ft_select): Likewise. + (ft_open): Improve debug information. + (ft_check_capability): New function. + (mfont__ft_driver): Specify ft_check_capability. + (mfont__ft_init): Initialize M0. + + * fontset.c (get_font_from_group): New function. + (mfontset__get_font): New function. + + * fontset.h (mfontset__get_font): Extern it. + + * font.c (OTF_tag): Define it if HAVE_OTF is undef. + (mfont__fini): Delete ifdef HAVE_OTF. + (free_font_capability): Likewise. + (mfont__get_capability): Likewise. + (mfont__check_capability): New function. + (mfont_check): Change the order of arguments. Use + mfontset__get_font. + + * font.h (struct MFontDriver): New member check_capability. + (MFontCapability): Delete ifdef HAVE_OTF. + (mfont__check_capability): Extern it. + + * face.c (mface__realize): Fix handling of FONT arg. + (mface__for_chars): Fix handling of explicitly specified font. + +2005-11-25 Kenichi Handa + + * font-flt.c (run_command): Print debug info for + left/rigth_padding + + * draw.c (layout_glyphs): Fix handling of left/right_padding. + + * face.c (mface__for_chars): Check rfont before accessing the + members. + +2005-11-21 Kenichi Handa + + * Makefile.am (lib_LTLIBRARIES): Define it conditionaly on + WITH_GUI. + + * fontset.c (fontset_table): New variable. + (free_fontset): Call M17N_OBJECT_UNREGISTER. + (mfont__fontset_init): Add fontset_table as an object array. + (mfont__realize_fontset): Ref FONTSET. + (mfont__free_realized_fontset): Unref REALIZED->fontset. + (mfontset): Call M17N_OBJECT_REGISTER. + (mfontset_copy): Likewise. + + * input.c (handle_key): For debugging, print information about + alias key. + (filter): Add an alias for Meta and Alt modifiers. + (Mcond, Mplus, Mminus, Mstar, Mslush, Mand, Mor, Mnot): New + variables. + (minput__init): Initialize them. + (parse_expression): New function. + (resolve_expression): New function. + (parse_action_list): Handle expressions by parse_expression. + (take_action_list): Handle expressions by resolve_expression. + (parse_nested_list_value): Fix previous change. + (resolve_command): Fix handling of the return value of + get_nested_list. + +2005-11-18 Kenichi Handa + + * font-ft.c (ft_check_otf, otf_script_list): Define only when + HAVE_OTF is defined. + (ft_list_capability): Call ft_check_otf only when HAVE_OTF is + defined. + (ft_select): Likewise. + + * font.c (mfont_list): Fix for the case that FONT is NULL. + (OTF_tag): Delete it. + (load_otf_script_list): Define only when HAVE_OTF is defined. + (mfont__fini): Unref otf_script_list only when HAVE_OTF is + defined. + + * draw.c (truncate_gstring): Be sure to truncate at + glapheme-cluster boundary. + +2005-11-11 Kenichi Handa + + * input.c (delete_surrounding_text): Clear cache if necessary. + +2005-11-09 Kenichi Handa + + * draw.c (compose_glyph_string): Update prev->rface->rfont if the + glyph prev is also supported by the current flt. + +2005-11-08 Kenichi Handa + + * m17n-X.c (xft_render): Cancel previous change. + +2005-11-07 Kenichi Handa + + * input.c: Include . + (get_surrounding_text, delete_surrounding_text) + (get_preceding_char, get_following_char): New functions. + (integer_value): New arg surrounding. If it is nonzero, try to + get a surrounding character. Callers changed. + (take_action_list): Check `value' before setting an element. + (destroy_ic): Unref ic_info->preceding_text and + ic_info->following_text. + (minput__init): Initialize Minput_get_surrounding_text and + Minput_delete_surrounding_text. + (Minput_get_surrounding_text, Minput_delete_surrounding_text): New + variables. + (filter): Unref ic_info->preceding_text and + ic_info->following_text. + + * m17n.h (Minput_get_surrounding_text, Minput_delete_surrounding_text): + Extern them. + + * input.h (MInputContextInfo): New members preceding_text and + following_text. + +2005-11-04 Kenichi Handa + + * input.c (parse_nested_list_value): Fix handling of the global + definition. + (get_nested_list): Get global definitions by load_partial_im_info. + (preedit_commit): Set ic->candidates_changed to bitwise or of enum + MInputCandidatesChanged. + (take_action_list): Likewise. + (reset_ic): Likewise. + (create_ic): Don't pay special attention to + Mcandidates_group_size. + (load_partial_im_info): Call mdatabase_find with correct 4th arg. + (minput_set_variable): Get a definition of varible by + mplist_find_by_value, not mplist_get. + + * m17n.h (enum MInputCandidatesChanged): New enum. + +2005-11-01 Kenichi Handa + + * m17n-X.c (xft_render): Check xft_draw's drawable before changing + it. + (mwin__destroy_window): If xft_draw's drawable is win, change it + to device->drawable before destroying win. + +2005-10-31 Kenichi Handa + + * input.c (load_im_info): Fix adding of state. + + * m17n-core.c (m17n_fini_core): Fix reporting of module + finalization. + + * m17n.c (m17n_fini): Fix reporting of module finalization. + + * m17n-gui.c (m17n_init_win): Fix reporting of module + finalization. + +2005-10-29 Kenichi Handa + + * input.c (get_candidate_list): Fix the timing of referring plist. + +2005-10-28 Kenichi Handa + + * input.c (load_branch): Ignore an undefined map name. + (load_im_info): Set im_info->title from `name' only if it's not + Mnil. + (shift_state): Always update ic->status. + (adjust_candidates): Renamed from adjust_candidate_command. + Argument changed. Caller changed. + (get_candidate_list, regularize_action): New functions. + (take_action_list): Use them. On handling Munhandle, don't set + ic_info->used to 0. + (handle_key): If KEY is not handled by MAP, and MAP has + branch_actions, perform them. + + * database.c (mdatabase__fini): Free dir_info->filename; + +2005-10-20 Kenichi Handa + + * input.c (marker_code): Accept '@@'. + (integer_value): Handle '@@'. + (parse_action_list): Accept a symbol argument. + (take_action_list): Resolve the symbol argument. Handle the + integer argument. + +2005-10-18 Kenichi Handa + + * input.c: Include "charset.h". + (M_candidates, Mcandidates_group_size, Mcandidates_charset): New + variables. + (MIMState): New member (M17NObject control). + (lookup_nested_list, set_nested_list, parse_nested_list_value) + (get_nested_list, resolve_variable): New functions. + (integer_value): New arg (MPlist **value). Set it to the plist + element containing the value. + (resolve_command): New function. + (load_translation): New arg (MPlist *map_actions). + (load_branch): New args language and name. If `keylist' is a + symbol, resolved that as a command name. + (free_map): New arg top. Free map->map_actions only if top is + nonzero. + (free_state): New function. + (load_state): New arg name. + (im_info_list): New variable. + (free_im_info, get_im_info_by_tags): New functions. + (load_im_info): Arg key changed to plist. Handle `include'. + Return (MInputMethodInfo *). + (preedit_commit): Ref ic->candidate_list. + (get_select_charset, adjust_candidate_command): New functions. + (take_action_list): Handle `include'. Adjust candidate action + properly. Handle control variables `candidates-charset' and + `candidates-group-size'. + (open_im): Use get_im_info. + (create_ic): Get global variables. + (load_partial_im_info): New function. + (get_im_info): New function. + (check_command_keyseq, check_command_list, check_variable_list): + New functions. + (minput__init): Don't handle M_database_hook and Mdetail_text. + Initialize M_candidates, Mcandidates_group_size, + Mcandidates_charset. + (parse_variable_list, get_variable_list, parse_command_list) + (get_command_list): Delete them. + (MDatabaseStatList, imdir_stat_list, input_method_hook): Delete them. + (minput__fini): Simply unref command_list and variable_list. + (minput_get_description): Adjusted for the new form of description. + (minput_get_commands): Use get_nested_list. + (minput_assign_command_keys): Likewise. + (minput_get_variables, minput_set_variable): Likewise. + + * input.h (MInputMethodInfo): New members im and maps. + + * database.h (M_database_hook): Delete extern. + (MDatabaseHookFunc): Delete extern. + (mdatabase__check): Extern it. + + * database.c: Include . + (MAX_TIME): New macro. + (Masterisk): New variable. + (get_database_stream): Argument changed to (MDatabaseInfo *). + Callers changed. + (get_dir_info): Renamed from duplicate_dirname. Callers changed. + (find_database): New function. + (update_database_list): New function. + (mdatabase__init): Initialize Masterisk. Setup mdb_list by + calling update_database_list. + (mdatabase__check): New function. + (mdatabase_find): Use update_database and find_database. Don't + handle MDatabaseHookFunc. + (mdatabase_list): Call update_database at first. + (mdatabase_define): Adjusted for the change of mdb->extra_info. + (MDatabaseList): New type. + + * plist.h (mplist_conv, mplist__pop_unref): Extern them. + + * m17n.h (Mdetail_text): Delete extern. + + * m17n-core.h (mplist_conc): Delete extern. + + * plist.c (mplist__conc): Renamed from mplist_conc. Don't ref + tail. + (mplist_conc): Renamed to mplist__conc. + (mplist__pop_unref): New function. + +2005-10-14 Kenichi Handa + + * plist.c (read_mtext_element): Ignore the sequence of '\\' and + newline. + (read_element): If keys is an empty plist, return any element + found first. + (dump_plist_element): Check if plist is nested. + (mplist_conc): Always ref tail. + (mplist_set): If key is a managing key, ref val in advance. + + * plist.h (MPLIST_VAL_MANAGED_P): Delete this macro. + (MPLIST_NESTED_P, MPLIST_SET_NESTED_P): New macros. + (MPLIST_ADD_PLIST, MPLIST_PUSH_PLIST, MPLIST_PUT_PLIST): New + macros. + + * fontset.c (free_fontset): Unref fontset_list if necessary. + (mfont__fontset_fini): Don't free fontset_list. Unref + default_fontset. + (mfont__realize_fontset): Initialize request. + (mfontset): Ref default_fontset or fontset only if necessary. + (mfontset_copy): Don't ref copy. + + * draw.c (render_glyphs): Check gend->type before checking + gend->to. + + * font-ft.c (mfont__ft_fini): Unref ft_default_list. Set all + unrefed plists to NULL. + +2005-10-04 Kenichi Handa + + * textprop.c (mtext_serialize): Be sure to make mt + MTEXT_FORMAT_UTF_8 and NULL terminated. + + * m17n-gui.c (m17n_init_win): Initialize Mcolormap. + + * draw.c (mdraw_glyph_list): Fix settting of glyphs->font->source. + +2005-10-03 Kenichi Handa + + * draw.c (mdraw_glyph_info): Pay attention to the case that FROM + is not at the beginning of line. + +2005-09-22 Kenichi Handa + + * input.c: Include and . + (Minclude, Mcommit, Munhandle): New variables. + (minput__init): Initialize them. Push only Mstate to + load_im_info_keys. Add aliases C-lowercase for C-uppercase. + (parse_action_list): Allow integer arg for undo. Handle Mcommit + and Munhandle. + (load_input_method): Handle "include" directive. If no states are + loaded, return -1. + (shift_state): If state_name is Mt, shift back to the previous + state. Call preedit_commit to commit preedit text. + (preedit_commit): New function. + (take_action_list): Improve debug printing. Handle commit and + unhandle commands. + (handle_key): Check the return value of take_action_list. Don't + take branch_actions just after changing to the root map. + (reset_ic): Reset all ic_info members. + (filter): When a key is not handled, just move ic_info->keys + instead fo calling reset_ic. + (load_im_info): If key is not Mstate, push Mmap to + load_im_info_keys. + (MDatabaseStatList): New type. + (imdir_stat_list): New variable. + (input_method_hook): Don't cancel the hook. Check the + modification time of directories. + (minput__fini): Free imdir_stat_list; + + * input.h (MInputContextInfo): New member prev_state. + + * m17n-core.h (mplist_conc): Extern it. + + * plist.c (mplist_conc): New function. + + * mtext.c (mdebug_dump_mtext): Escape '"' and '\\' by '\\'. + + * font.h (MRealizedFont): New member average_width. + + * font-ft.c (ft_open): Set rface->average_width. + + * font.c (xlfd_unparse_name): Print '*' before registry name. + + * m17n-X.c (MDisplayInfo): New member AVERAGE_WIDTH. + (xfont_open): Set rfont->average_width. + (xft_open): Likewise. + (device_open): Initialize disp_info->AVERAGE_WIDTH. + + * internal-gui.h (struct MFrame): New member average_width. + + * m17n-gui.c (mframe): Fix setting of frame->rfont. + (mframe_get_prop): Return the average_width of a font. + + * face.c (mface__realize): Set rface->average_width. + (mface__update_frame_face): Set frame->average_width. + + * face.h (MRealizedFace): New member average_width. + +2005-09-19 Kenichi Handa + + * font.c (xlfd_unparse_name): New arg full_xlfd. + (mfont__encode_char): Use shortcut only for X core fonts. + (mfont_unparse_name): Call xlfd_unparse_name with full_xlfd arg 1. + (mfont_put_prop): Handle `language' property. + (mdebug_dump_font): Call xlfd_unparse_name with full_xlfd arg 0. + Print file can capability info too. + + * m17n-core.c (mdebug__output): New variable. + (SET_DEBUG_FLAG): Unset mask if env_value is '0'. + (m17n_init_core): Handle MDEBUG_ALL and MDEBUG_OUTPUT_FILE. + (m17n_fini_core): Close mdebug__output if it's not stderr. + + * m17n-X.c (MDisplayInfo): New member MULE_BASELINE_OFFSET. + (xfont_open): Handle baseline_offset. + (xfont_find_metric): Likewise. + (xfont_render): Likewise. + (xft_open): Likewise. + (xft_render): Likewise. + + * internal.h (MDebugMaskBit): Add MDEBUG_ALL. + (mdebug__output): Extern it. + (MDEBUG_PRINT, MDEBUG_PRINT1, MDEBUG_PRINT2, MDEBUG_PRINT3) + (MDEBUG_PRINT4, MDEBUG_PRINT5): Print to medebug__output. + (MDEBUG_DUMP): New macro. + (MDEBUG_PRINT_TIME): Print to medebug__output. + + * font.h (MRealizedFont): New member baseline_offset. + + * font-ft.c (ft_get_charmaps): Check if the font support iso8859-1 + characters. + (fc_weight_table): Add FC_WEIGHT_REGULAR. + (ft_list_family): Check alias. + (ft_list_language): If language is "en", don't try to the second + step. + (ft_default_list): New variable. + (ft_list_default): New function. + (ft_select): If family is not specified, try only the default + fonts. Treat the weights normal and medium same. + (ft_open): Fix debug message. If registry is not specified, try + unicode-bmp. Handle _MULE_BASELINE_OFFSET property of BDF fonts. + (ft_find_metric): Likewise. + (ft_render): Likewise. + (ft_list): Fix debug message. Accept the registring iso8859-1. + If family is not specified, try only the default fonts. + + * face.c (mface__realize): Fix logic of opening a font. + +2005-09-16 Kenichi Handa + + * face.c (mface__realize): + + * m17n.h (Minput_focus_move, Minput_focus_in, Minput_focus_out): + Extern them. + + * input.c (shift_state): Fix the condition of taking init actions. + (take_action_list): Fix handling of pushback action. + (handle_key): Don't change key while checking its alias. + (minput__init): Initialize new variables. + (Minput_focus_move, Minput_focus_in, Minput_focus_out): New + variables. + +2005-09-12 Kenichi Handa + + * mtext.c (mtext__uppercase): Add proper open/close parens. + (mtext_titlecase): Add proper casting. + + * input.c (parse_action_list): Handle the case that the arg is a + key sequence (MText or MPlist). + (take_action_list): Likewise. + (shift_state): Shorter debug message. + (handle_key): Terminate a debug message by "\n". + (reset_ic): Don't take initial actions here. + (minput_open_im): Print a debug message. + (minput_close_im): Likewise. + (minput_create_ic): Likewise. + (minput_destroy_ic): Likewise. + +2005-09-09 TAKAHASHI Naoto + + * mtext.c (mtext_lowercase, mtext_titlecase, mtext_uppercase): + Change API. + +2005-09-07 TAKAHASHI Naoto + * character.c: Add "cased", "soft-dotted", and "case-mapping" in + mchar__init (). + + * character.c: Add Japanese documentation for + mchar_get_prop_table (). + +2005-09-06 TAKAHASHI Naoto + + * mtext.c (tricky_chars, *cased, *soft_dotted, *case_mapping) + (MCharTable *combining_class, Mlt, Mtr, Maz, gr03A3, lt0049, + (lt004A, lt012E, lt00CC, lt00CD, lt0128, tr0130, tr0049, tr0069): + New variables. + (init_case_conversion): New function. + (CASE_CONV_INIT, REPLACE, DELETE, LOOKUP): New macros. + (uppercase_precheck, lowercase_precheck, final_sigma) + (after_soft_dotted, more_above, before_dot, after_i) + (mtext_uppercase, mtext_titlecase, mtext_lowercase): New functions. + +2005-09-05 TAKAHASHI Naoto + + * plist.c (read_mtext_element): Fix previous change. + +2005-09-05 Kenichi Handa + + * plist.c (read_mtext_element): Handle \uXXXX notation. + + * internal.h (MTABLE_MALLOC): Don't use a local variable. + (MTABLE_ALLOCA): Change the name of local variable. + + * m17n-gd.c (device_open): Define it even if HAVE_GD nor + HAVE_FREETYPE are defined. + + * m17n-X.c: Check HAVE_X11. + + * Makefile.am (X_LD_FLAGS): Use @X11_LD_FLAGS@ instead of + directory listing libraries. + (noinst_PROGRAMS): Define it only in maintainer mode. + +2005-09-02 Kenichi Handa + + * m17n-gui.h (mdraw_line_break_option): Extern it. + + * draw.c (truncate_gstring): Use find_glyph_in_gstring to find the + end of the first glyph. + (GET_LB_TYPE, find_break_backward, find_break_forward): Delete + them. + (mdraw_line_break_option): New variable. + (mdraw_default_line_break): Use mtext_line_break. + + * mtext.h (wordseg_func_table): Don't extern it. + (mtext__wseg_fini): Extern it. + + * mtext.c: Don't include word-thai.h. + (wordseg_func_table): Delete this variable. + (mtext__init): Don't initialize above. Don't call + mtext__word_thai_init. + (mtext__fini): Don't free wordseg_func_table. Call + mtext__wseg_fini instead fo mtext__word_thai_fini. + (MTextWordsegFunc): Don't typedef it. + (mtext__word_segment): Moved to mtext-wseg.c. + + * m17n-core.h (enum MTextLineBreakOption): New enum. + (mtext_line_break): Extern it. + + * mtext-wseg.c: New file. + + * mtext-lbrk.c: New file. + + * Makefile.am (libm17n_core_la_SOURCES): Delete word-thai.[ch], + add mtext-lbrk.c and mtext-wseg.c. + + * textprop.c (mtext__adjust_plist_for_change): Pay attention for + the case that head is NULL. + +2005-09-01 Kenichi Handa + + * word-thai.c (wordseg_propertize): If the property value is nil, + don't make the property no-merge. + (thai_wordseg): Don't require *from and *to are set a priori. Pay + attention to the case that they are NULL. + (mtext__word_thai_init): Make the name of Mthai_wordseg starts + with two spaces. + + * character.c (mchar_get_prop_table): New function. + + * textprop.h (mtext__adjust_plist_for_change): Prototype adjusted. + + * m17n-core.h (mtext_insert, mtext_replace): Extern them. + (mchar_get_prop_table): Extern it. + + * textprop.c (prepare_to_modify): New arg deleting. Callers changed. + (mtext__adjust_plist_for_change): Argument changed. Callers changed. + + * internal.h (enum MTextCoverage): New enum. + (MText): New member coverage. + + * mtext.c (FORMAT_COVERAGE): New macro. + (insert): Copy mt2->coverage. + (mtext__from_data): Initialize mt->coverage. + (mtext__adjust_format): Update mt->coverage. + (mtext): Initialize mt->coverage. + (mtext_set_char): Adjust args to mtext__adjust_plist_for_change. + Update mt->coverage if necessary. + (mtext_duplicate): Copy mt->coverage. + (mtext_insert, mtext_replace): New functions. + (mtext_dup): Use mtext_duplicate. + (mtext__word_segment): Don't set *from and *to if a word + segmentation funcion is not found. + (mtext_ins_char): Fix typo. + +2005-08-25 Kenichi Handa + + * font.h (MFont): New member for_full_width. + + * font.c (compare_font_score): Prefer a font of not + for_full_width. + + * m17n-X.c (xfont_registry_list): Set font.for_full_width if the + registry charset of a font is one of CJK charsets. + + * font-ft.c (fc_parse_pattern): Set font->for_full_width if a font + supports some of CJK. + +2005-08-24 Kenichi Handa + + * m17n-gui.h (Mascent, Mdescent): Don't extern them. + + * m17n-gui.c (null_device_open): Check Mresolution param and set + frame->dpi. + + * m17n-gd.c (device_open): Check Mresolution param and set + frame->dpi. + + * m17n-X.c (MWDevice): New member resy. + (xfont_open): Set ascent, descent, and max_advance members of + rfont. + (xft_open): Likewise. + (device_open): Compare also screen_num to find a device. Set + device->resy and frame->dpi. + + * internal-gui.h (MFrame): New member dpi. + + * font.h (MRealizedFont): New member max_advance. + + * font.c (xlfd_unparse_name): Handle the case of font->size < 0. + (mfont__init): Don't initialize Mascent, Mdescent. + (Mascent, Mdescent): Delete these variables. + (mfont_get_prop): Fix previous change. Check Mfont_ascent and + Mfont_descent instead of Mascent and Mdescent. + (mfont_put_prop): Allow negative size. + (mfont_find): Handle the case of spec->size < 0. Fix previous + change. + (mfont_list): Handle the case of spec->size < 0. + (mfont_check): Likewise. + + * font-ft.c (STRDUP_LOWER): Ignore the tailing spaces. + (fc_get_pattern): Handle the case of font->size < 0. + (ft_open): Set ascent, descent, and max_advance members of rfont. + (ft_find_metric): Improve rounding. + (mfont__ft_parse_name): If FC_PIXEL_SIZE is not available, set + FC_SIZE. + + * face.c (mface__realize): Handle the case of font->size < 0. + +2005-08-22 Kenichi Handa + + * coding.c (MConverterStatus): Change the member buf to union. + (mconv_buffer_converter): Add const to the arg buf. + (mconv_decode_buffer, mconv_rebind_buffer): Likewise. + (mconv_decode): Adjusted for the change of MConverterStatus. + (mconv_encode_range): Likewise. + + * m17n.h (mconv_buffer_converter): Prototype adjusted. + (mconv_decode_buffer, mconv_rebind_buffer): Likewise. + +2005-08-20 Kenichi Handa + + * m17n-gui.h (mfont_from_name): Prototype adjusted. + (Mspacing, Mascent, Mdescent, Mmax_advance): Extern them. + + * m17n-X.c (xfont_open): Set members ascent, descent, and + max_advance of rfont. + (xft_open): Likewise. + + * font-ft.c (ft_open): Set members ascent, descent, and max_advance + of rfont. + (mfont__ft_parse_name): Add const to the arg name. + + * font.c (xlfd_parse_name): Add const to the arg name. Call + mfont__set_property instead of mfont_set_spec. Set font->spacing. + (xlfd_unparse_name): Handle spacing. + (mfont__init): Initialize new variables. + (mfont__id): Handle spacing. + (mfont__merge): Likewise. + (mfont__set_spec): This function deleted. + (mfont__parse_name_into_font): Add const to the arg name. Fix the + condition of calling mfont__ft_parse_name. + (Mspacing, Mascent, Mdescent, Mmax_advance): New variables. + (mfont_get_prop): Handle properties spacing, ascent, descent, + and max-advance. + (mfont_find): Return a realized font. + (mfont_from_name): Add const to the arg name. + + * font.h (enum MFontProperty): New member MFONT_SPACING. + (enum MFontSpacing): New enum. + (MFont): New members spacing and max_advance. + (mfont__ft_parse_name): Prototype adjusted. + (mfont__set_spec): Extern deleted. + (mfont__parse_name_into_font): Prototype adjusted. + +2005-08-19 Kenichi Handa + + * m17n-gui.h (mfont_parse_name): Prototype adjusted. + + * font.c (mfont_list): If FONT is null, use a temporary font. + (mfont_parse_name): Add const to the arg name. + +2005-08-18 Kenichi Handa + + * word-thai.c: Surround code by #ifdef and #endif to escape from + doxygen. + + * font-ft.c: Mostly re-written. + + * font-flt.c (FontLayoutCmdOTF): This type deleted. + (FontLayoutCmd): Type of the member otf changed.. + (load_otf_command): Adjusted for the format change of otf command. + (load_command): Likewise. + (free_flt_command): Unref cmd->body.otf. + (run_otf): Ajusted for the type change of otf_cmd. + (run_command): Ajusted for the type change of otf_cmd. On + debugging, print ctx->combining_code. + (mfont__flt_run): Initialize ctx's members code_offset, + combining_code, and left_padding to 0. + + * face.h (struct MRealizedFace): New member font. + (mface__realize): Prototype adjusted. + + * face.c (find_realized_face): New arg font. + (find_realized_face): Adjusted for the change of MFont. + (mface__init): Call M17N_OBJECT_ADD_ARRAY. + (mface__fini): Don't call mdebug__report_object. + (mface__realize): New arg font. + (mface__for_chars): Adjusted for the change of mfont__encode_char. + Optimize the latin case. + (mface__free_realized): Free rface->font. + (mface__update_frame_face): Adjusted for the change of mface__realize. + (mface_equal): New function. + + * draw.c (Mcommon): New variable. + (visual_order): Args to mfont__encode_char changed. + (compose_glyph_string): Handle Mfont text property. + (layout_glyphs): Adjusted for the change of MFont. + (mdraw__init): Initialize Mcommon. + (mdraw_glyph_info): Adjusted for the change of MRealizedFont. + + * font.h (enum MFontType): Members completely changed. + (enum MFontProperty): Move MFONT_SIZE to the tail. + (enum MFontSource): New enum. + (struct MFont): New members type, source, sizes, file, capability, + and encoding. + (struct MRealizedFont): Type of member font changed. Members + score, status, and encoding deleted. + (MFontScore): New type. + (MFontList): Member changed. + (struct MFontDriver): New member has_char. Types of members + changed. + (Miso8859_1, Miso10646_1, Municode_bmp, Municode_full) + (Mapple_roman): Extern them. + (OTF_Tag): Typedefed if not HAVE_OTF. + (enum MFontOpenTypeTable): New enum. + (MFontCapability): New type. + (mfont__ft_drive_otf): Prototype adjusted. + (mfont__score): Extern deleted. + (mfont__merge): Extern it. + (mfont__has_char): Extern it. + (mfont__encode_char): Prototype adjusted. + (mfont__open): Extern it. + (mfont__set_spec): Prototype adjusted. + (mfont__get_capability): Extern it. + + * font.c: Include "fontset.h". + (M_font_capability, M_font_list, M_font_list_len): New variables. + (font_score_priority): Change order of initial elements. + (font_score_shift_bits): Fix array size. + (common_weight): Add "thin", "semibold", and "heavy". + (common_stretch): Add "ultracondensed", "extracondensed", + "extraexpanded", and "utltraexpand". + (font_weight_regular, font_weight_normal, font_weight_medium): New + variables. + (gen_font_name): This function deleted. + (find_encoding): Set font->encoding. + (OTF_tag): New function. + (otf_script_list): New variable. + (load_otf_script_list): New function. + (find_script_from_otf_tag): New function. + (xlfd_parse_name): Set font->type and font->source. + (mfont__free_realized): Free chains rfonts. + (font_score): Renamed from mfont__score. + (Miso8859_1, Miso10646_1, Municode_bmp, Municode_full) + (Mapple_roman): New variables. + (mfont__init): Initilize new variables. Initalize + default_encoding.encoding_name and + default_encoding.encoding_charset to Municode_full and + mcharset__unicode. Use SAFE* macros for allocating filepath + buffer. + (mfont__fini): Free otf_script_list. + (mfont__id): New function. + (mfont__match_p): Check also capability member of MFont. + (mfont__merge): New funciton. + (mfont__set_spec_from_face): Set type and source members. + (mfont__set_spec_from_plist): Set capability and type members. + (mfont__select): Argument changed. + (mfont__available): New function. + (compare_font_score): New function. + (mfont__list): New function. + (mfont__open): Return a realized font. + (mfont__resize): Adjusted for the change of MFont. + (mfont__has_char): New function. + (mfont__encode_char): Argument changed. + (mfont__set_spec): Argument changed. + (free_font_capability): New function. + (mfont__get_capability): New function. + (MFontfile): New variable. + (mfont_get_prop): Adjusted for the change of MFont. + (mfont_put_prop): Likewise. + (mfont_set_selection_priority): Fix the way of setting + font_score_priority[]. + (mfont_find): Use mfont__list instead of mfont__select. + (mfont_resize_ratio): Adjusted for the change of MFont. + (mfont_list): Use mfont__list. + (mfont_check): New function. + (font_score): Make it static. + + * fontset.h (mfont__realize_fontset): Prototype adjusted. + (mfont__lookup_fontset): Likewise. + + * fontset.c (struct MFontset): Delete member font_spec_list. + (struct MRealizedFontset): Type of member spec changed. New + member request. + (load_font_group): Arg spec_list deleted. + (load_fontset_contents): Adjusted for the change of fontset_def. + (free_fontset): Fix the way of freeing fontset elements. + (realize_fontset_elements): Argument changed. + (get_per_script): New function. + (free_realized_fontset_elements): Fix the way of feeing rfontset + elements. + (update_fontset_elements): Fix args to realize_fontset_elements. + (mfont__realize_fontset): New arg spec. + (try_font_list): New function. + (try_font_group): New arg request. Use try_font_list. + (mfont__lookup_fontset): New arg ignore_fallback. Fix arg to + try_font_group. + (mfontset): Adjusted for the change of MFontset. + (mfontset_copy): Likewise. Don't share plists. + (mfontset_modify_entry): Adjusted for the change of MFontset. + (mfontset_lookup): Call get_per_script. + (mdebug_dump_fontset): Print also the address of fonts. + + * input.c (shift_state): Don't reset ic_info->vars. + (take_action_list): Call MDEBUG_PRINT fore calling + take_action_list. + + * internal-gui.h (MFontDriver): Don't typedef it here. + + * m17n-X.c: Include if HAVE_XFT2. + (MXFont): This type deleted. + (MFontX): New type. + (struct _MFontX): New struct. + (SET_SIZE, HAVE_SIZE): Adjusted for the change of arg FONTX. + (MDisplayInfo): Member base_font_list deleted. + (DEFAULT_FONT): Definition changed. + (FALLBACK_FONT): This maclr deleted. + (free_display_info): Adjusted for the change of MDisplayInfo. + (free_device): Argument to mfont__free_realized changed. + (xfont_driver): Adjusted for the change of MFontDriver. + (xfont_registry_list): Use MFontX instead of MXFont. + (MRealizedFontX): Renamed from MXFontInfo. + (xfont_select): Return the font found first. + (close_xfont): Change MXFontInfo to MRealizedFontX. + (xfont_open): Return the realized font. + (xfont_find_metric): Get xfont from rfont->fontp. + (xfont_has_char): New function. + (xfont_encode_char): Adjusted for the argument change. + (xfont_render): Get xfont from rfont->fontp. + (xfont_list): Adjusted for the argument change. + (MRealizedFontXft): Renamed from MXftFontInfo. + (xft_driver): Ajusted for the change of MFontDriver. + (close_xft): Change MXtfFontInfo to MRealizedFontXft + (xft_open_font): Argument changed. + (xft_open): Argument changed. Return the realized font. + (xft_find_metric): Get xft_font from rfont->fontp. + (xft_has_char, xft_encode_char): New functions. + (xft_render): Change MXftFontInfo to MRealizedFontXft. Open a + font if not yet opened. + (device_open): Don't set frame->font. + + * m17n-gd.c (gd_font_driver): Adjusted for the change of + MFontDriver. + (gd_font_open): New function. + (gd_render): Don't use the local variable ft_info. + (device_init): Adjusted for the change of gd_font_driver. + + * textprop.c (mtext__prop_init): Initialize text_property_table. + Call M17N_OBJECT_ADD_ARRAY. + (mtext__prop_fini): Don't call mdebug__report_object. + + * plist.c (mplist__init): Initialize plist_table. + (mplist__init): Call M17N_OBJECT_ADD_ARRAY. + (mplist__fini): Don't call mdebug__report_object. + + * mtext.c (mtext__init): Call M17N_OBJECT_ADD_ARRAY. + (mtext__fini): Don't call mdebug__report_object. + (MTEXT_FORMAT_UTF_16): Correct type. + (mtext_data): New function. + (mtext_text): Fix calculation of limit and args to + find_char_backward. + + * language.c: Include "plist.h". + (M_script_lang_list): New variable. + (mlang__init): Read languages and their information from m17n + database. + (mlanguage__list): New function. + (Miso639_1, Miso639_2): New variables. + + * language.h (mlanguage__list): Extern it. + + * database.c (get_database_stream): Use SAFE_* macros for + allocating and freeing path. + (mdatabase__init): Likewise. + + * symbol.c (msymbol__fini): Don't free symbols here. + (msymbol__free_table): New function. + (msymbol_is_managing_key): New function. + + * symbol.h (msymbol__free_table): Extern it. + (msymbol__list): Extern it. + + * internal.h (MFATAL, USE_SAFE_ALLOCA, SAFE_ALLOCA, SAFE_FREE): + New macros. + (M17N_OBJECT_UNREF): Change "if ... else ..." structure. + (struct _M17NObjectArray): New member name and next. + (mdebug__add_object_array): Extern it. + (M17N_OBJECT_ADD_ARRAY): New macro. + (mdebug__report_object): Don't extern it. + + * m17n-misc.h (enum MErrorCode): New element MERROR_FONT_X. + + * m17n-gui.c (free_frame): Don't free frame->font. + (null_device_fini): Fix code for freeing + null_device.realized_font_list. + (m17n_fini_win): Free interface. + (mframe): Cast the return value of dlsym. Set frame->font here. + (mframe_get_prop): Check frame->rface->rfont before accessing the + member font. + + * m17n-gui.h (Mfontfile): Extern it. + (mfont_check): Extern it. + (mface_equal): Extern it. + + * m17n-core.c: Include "symbol.h". + (report_header_printed): This variable deleted. + (object_array_root): New variable. + (report_object_array): New function. + (mdebug__report_object): This function deleted. + (mdebug__add_object_array): New function. + (m17n_init_core): Call mchartable_init () before mtext_init (). + (m17n_fini_core): Call report_object_array (if necessary) and + msymbol__free_atable at the end. + + * m17n-core.h (msymbol_is_managing_key): Extern it. + (mtext_data): Extern it. + (MTEXT_FORMAT_UTF_16): Correct type. + (M17NLIB_MINOR_VERSION): Changed to 3. + (M17NLIB_VERSION_NAME): Changed to "1.3.0". + + * chartab.c (mchartable__init): Initalize chartable_table.count. + (mchartable__fini): Use N17N_OBJECT_ADD_ARRAY instead of + mdebug__report_object. + +2005-05-26 Kenichi Handa + + * m17n.h (Miso639_1, Miso639_2): Extern them. + + * symbol.h (msymbol__list): Extern it. + + * symbol.c (msymbol__list): New function. + +2005-05-19 Kenichi Handa + + * input-gui.c (minput__win_init): Don't change the value of + minput_driver. + +2005-05-16 Kenichi Handa + + * m17n-core.c (m17n_object): Be sure to initialize all members. + + * font-ft.c (fc_decode_prop): Fix args to msymbol. + +2005-05-09 Kenichi Handa + + * m17n-X.c (mwin__close_device): Fix arg to M17N_OBJECT_UNREF. + +2005-04-27 Kenichi Handa + + * language.c (mlang__init): Add "an" (Aragonese). + + * word-thai.c: Add support for libthai. + (mtext__word_thai_init): Initialize wordseg library conditionaly. + (mtext__word_thai_fini): Finalize wordseg library conditionaly. + + * mtext.c: Include "word-thai.h" conditionaly. + (mtext__init): Call mtext__word_thai_init conditionaly. + (mtext__fini): Call mtext__word_thai_fini conditionaly. + + * Makefile.am (libm17n_core_la_LIBADD): Add THAI_WORDSEG_LD_FLAGS, + not WORDCUT_LD_FLAGS. + +2005-04-19 Kenichi Handa + + * word-thai.c (wordseg_propertize): Always unref the attached + property. + (thai_wordseg): Don't unref the property. + +2005-04-18 Kenichi Handa + + * word-thai.c: Include stdlib.h. + (wordseg_propertize): Add dummy function for the case that wordcut + library doesn't exist. + (wordseg_propertize): Fix for old wordcut library. + +2005-04-16 Kenichi Handa + + * word-thai.c: Include . + +2005-04-15 Kenichi Handa + + * draw.c: Include mtext.h. + (linebreak_table, M_break_at_space, M_break_at_word) + (M_break_at_any, M_kinsoku_bol, M_kinsoku_eol): New variables. + (compose_glyph_string): Check POS before getting Mface text + property. + (truncate_gstring): Give correct TO arg to line_break function. + (GET_LB_TYPE): New macro. + (find_break_backward, find_break_forward): New functions. + (mdraw__init): Initialize the above new variables. + (mdraw__fini): Free linebreak_table. + (mdraw_default_line_break): Use find_break_backward and + find_break_forward. + + * word-thai.c: New file. + + * word-thai.h: New file. + + * mtext.c: Include word-thai.h. + (wordseg_func_table): New variable. + (mtext__init): Initialize wordseg_func_table and call + mtext__word_thai_init. + (mtext__fini): Call mtext__word_thai_fini, free + wordseg_func_table. + (MTextWordsegFunc): New type. + (mtext__word_segment): New function. + + * mtext.h (wordseg_func_table): Extern it. + (mtext__word_segment): Extern it. + + * m17n.c (m17n_init): Fix typo (== -> =). + + * Makefile.am (libm17n_core_la_SOURCES): Include word-thai.[ch]. + (libm17n_core_la_LIBADD): Add @WORDCUT_LD_FLAGS@. + + * textprop.h (MTEXTPROP_START, MTEXTPROP_END, MTEXTPROP_KEY) + (MTEXTPROP_VAL): New macros. + + * input.c (DLOPEN_SHLIB_EXT): Don't define it. + +2005-04-07 Kenichi Handa + + * database.c (load_chartable): Fix pursing of symbol name. + +2005-03-24 Kenichi Handa + + * m17n.c (m17n_init): Fix typo (== -> =). + +2005-03-11 Kenichi Handa + + * m17n-gui.c (m17n_init_win): Set merror_code to MERROR_NONE at first. + + * m17n.c (m17n_init): Set merror_code to MERROR_NONE at first. + + * m17n-core.c (m17n_init_core): Set merror_code to MERROR_NONE at + first. + +2005-03-09 handa + + * m17n-gui.c (m17n_init_win): Set merror_code to MERROR_NONE before + calling m17n_init (). + + * m17n.c (m17n_init): Set merror_code to MERROR_NONE before + calling m17n_init_core (). + +2005-02-28 Kenichi Handa + + * font-flt.c (mfont__flt_run): Add resulting code sequence in + debug info. + +2005-02-17 Kenichi Handa + + * input.c: Include , , and "database.h". + (M_description, M_command, M_variable): New variables. + (load_im_info_keys): New variables. + (load_im_info, check_command_keyseq, get_description_advance) + (parse_command_list, get_command_list, parse_variable_list) + (get_variable_list, input_method_hook): New functions. + (command_list, variable_list): New variables. + (minput__init): Put input_method_hook to Minput_method. + Initialize M_description, M_command, M_variable, Mdetail_text, + load_im_info_keys, command_list, variable_list. + (minput__fini): Unref command_list, variable_list, load_im_info_keys. + (Mdetail_text): New variable. + (minput_get_description, minput_get_commands) + (minput_assign_command_keys, minput_get_variables) + (minput_set_variable): New functions. + + * m17n.h (Mdetail_text, minput_get_description, minput_get_commands) + (minput_assign_command_keys, minput_get_variables) + (minput_set_variable): Extern them. + + * plist.c (UNGETC): Just decrement st->p. + (read_mtext_element): New arg skip. + (read_integer_element): Likewise. + (read_symbol_element): Likewise. + (read_element): New arg KEYS. + (mplist__from_plist): Don't increment ref-count of NULL object. + (mplist__from_file): New arg KEYS. + (mplist_put): Don't increment ref-count of NULL object. + (mplist_add): Likewise. + (mplist_push): Likewise. + (mplist_set): Likewise. Call M17N_OBJECT_UNREF unconditionally. + + * plist.h (mplist__from_file): Prototype adjusted. + + * database.c (mdatabase__dir_list): Renamed from mdb_dir_list. + (get_database_stream): New function. + (load_database): Use get_database_stream. + (M_database_hook): New variable + (mdatabase__init): Initialize M_database_hook. + (mdatabase__load_for_keys): New function. + (mdatabase_find, mdatabase_list, mdatabase_define): Check hook + function. + (mdatabase_define): Free mdb->extra_info if necessary. + + * database.h (mdatabase__dir_list, M_database_hook) + (mdatabase__load_for_keys): Extern them. + (MDatabaseHookFunc): New type. + + * internal.h (M17N_OBJECT_UNREF): When freed, set OBJECT to NULL. + +2004-12-27 Kenichi Handa + + * Version 1.2.0 released. + +2004-12-27 Kenichi Handa + + * input.c (minput_filter): Don't reset ic->xxx_changed. + + * mtext.c (mtext_from_data): Fix documentation. + +2004-12-25 Kenichi Handa + + * m17n-core.h (M17NLIB_MINOR_VERSION): Update to 2. + (M17NLIB_VERSION_NAME): Update to "1.2.". + +2004-12-24 Kenichi Handa + + * input.c (reset_ic): Set key_unhandled to 0. + +2004-12-21 Kenichi Handa + + * m17n-gui.h (mfont_from_spec): Delete extern. + + * input-gui.c (win_callback): Handle Minput_reset. + (minput__win_init): Register reset_ic as a callback for + Minput_reset. + + * input.c (reset_ic): New arg IGNORE which is ignored. Caller + changed. At first, shift to the initial state. + (minput__init): Initialize Minput_reset. Register reset_ic as a + callback for Minput_reset. + (Minput_reset): New variable. + (minput_filter): Always set ic->xxx_changed to 0. + (minput_reset_ic): New function. + (integer_value): Fix typo ('>' -> '<') and calculation of length + of preedit text. + + * m17n-core.c (merror_code): Change type to `int'. + + * m17n-misc.h (merror_code): Adjust type. + + * m17n.h (Minput_reset, minput_reset_ic): Extern them. + + * m17n-core.h (MTEXT_FORMAT_UTF_16, MTEXT_FORMAT_UTF_32): Adjust types. + (mtext_change_prop): Delete extern. + + * mtext.c (MTEXT_FORMAT_UTF_16, MTEXT_FORMAT_UTF_32): Change types + to `int'. Move the documents to m17n-core.h. + +2004-12-13 Kenichi Handa + + * m17n-core.h (m17n_object): Rename extern from m17n_object_setup. + (MTextProperty): Document it. + +2004-12-09 Kenichi Handa + + * m17n-core.h: Fix typo (MTextStatus -> M17NStatus). + +2004-12-03 Kenichi Handa + + * internal.h (m17n__core_initialized, m17n__shell_initialized, + m17n__gui_initialized): New externs. + + * m17n-core.h (enum M17NStatus): New enum. + (m17n_status): Extern it. + + * m17n-core.c (core_initialized): Delete this variable. + (m17n__core_initialized, m17n__shell_initialized, + m17n__gui_initialized): New variables. + (m17n_init_core, m17n_fini_core): Check m17n__core_initialized + instead of core_initialized. + (m17n_status): New function. + + * m17n.c (shell_initialized): Delete this variable. + (m17n_init, m17n_fini): Check m17n__shell_initialized instead of + shell_initialized. + + * m17n-gui.h (m17n_init_win): Adjust the prototype. + + * m17n-gui.c (win_initialized): Delete this variable. + (m17n_init_win, m17n_fini_win): Check m17n__gui_initialized + instead of gui_initialized. + +2004-11-19 Kenichi Handa + + * input.c (reset_ic): Check if ic_info->state is NULL. + (filter): If ic_info->state is NULL, return 0. + (load_input_method): Don't unref `maps' it it's not created. + +2004-11-15 Kenichi Handa + + * input.c (find_candidates_group): If INDEX is -1, find the last + candidate group. + (take_action_list): If the previous of the first candidate is + requested, select the last candidate. + +2004-11-08 Kenichi Handa + + * m17n-X.c (device_open): Try at most 32 fonts to find a + non-autoscaled font. + + * font.c (xlfd_parse_name): Fix previous change. + +2004-11-05 Kenichi Handa + + * font.c: (commont_style): Include dummy elements "slanted" and + "rslanted" to prefer "o" to "r" if "i" is requested. + + * font-ft.c (ft_to_prop): Fix "oblique" entry. + +2004-10-29 Kenichi Handa + + * font.c (xlfd_parse_name): If avgwidth is 0, set the size to 0. + + * m17n-X.c (MXFont): Change type of the member `sizes' to int. + New members smallest and larger. + (SET_SIZE, HAVE_SIZE): Adjusted for the above change. + (xfont_registry_list): Likewise. + (xfont_select): Likewise. + + +2004-10-28 Kenichi Handa + + * m17n-X.c (xfont_registry_list): Include '-' before PIXEL_SIZE in + font name comparison. + (xfont_select): Fix logic for selecting a larger size font. + +2004-10-25 Kenichi Handa + + * input.c (take_action_list): Initialize `ret' to 0 for "=", "<", + ">" actions. + +2004-10-22 Kenichi Handa + + * input.c (update_candidate): Renamed from udpate_candidate. + (take_action_list): Show more debugging info on arithmetic commands. + + * m17n-X.c (device_open): Fix previous change. + + * draw.c (compose_glyph_string): Don't get face property at the + end of M-text. + +2004-10-21 Kenichi Handa + + * draw.c (compose_glyph_string): Fix for the case of category + being Mnil. + +2004-10-19 Kenichi Handa + + * input.c (mdebug_mask): New variable. + (shift_state): Print debug information. + (take_action_list): Likewise. + (handle_key): Likewise. + +2004-10-14 Kenichi Handa + + * m17n-X.c (device_open): Accept Mxft as the value of key Mfont. + +2004-10-13 Kenichi Handa + + * m17n-X.c (device_open): Be sure to register at least one font + driver. + + * font-ft.c: Include conditionally. Check + HAVE_FTBDF_H before calling FT_Get_BDF_Property. + +2004-10-12 Kenichi Handa + + * draw.c (alloc_gstring): Fix previous change. + + * font-ft.c (ft_list_generic): Fix for the case of not + HAVE_FONTCONFIG. + + * m17n-X.c (mwin__parse_event): Fix for non-ASCII keys. + + * font.c (mfont_list): If no font is found, return NULL. + (load_font_encoding_table): Put entries of nil registry first. + (find_encoding): Adjust for the above change. + +2004-10-11 Kenichi Handa + + * m17n-gui.h (mfont_list): Adjust prototype. + + * m17n-X.c (xfont_list): New arg maxnum. + + * font.h (struct MFontDriver): Change prototype of . + + * font-ft.c (fc_generic_family_list): Delete it. + (Mserif, Msans_serif, Mmonospace): Delete them. + (M_generic_family_info): New variable. + (enum GenericFamilyType): New enum. + (struct GenericFamilyInfo): New struct. + (generic_family_table): New variable. + (set_font_info): New arg style. Don't check 0xA0..0xBF to decide + iso8859-1. + (add_font_info): Get style here. + (ft_list_family): Don't initialize fc_config here. Don't list + generic families. + (ft_list_generic): New function. + (ft_select): Pay attention to generic familes here. + (ft_open): Fix calculation of ascent and descent. + (ft_list): Pay attention to generic families. + (mfont__ft_init): Initialize M_generic_family_info, + generic_family_table, and fc_config.. + (mfont__ft_fini): Finalize generic_family_table. + + * draw.c (compose_glyph_string): Use more constant font for + glyphs. Adjust for the member change in MGlyph. + (layout_glyph_string): Adjust for the member change in MGlyph. + (alloc_gstring): Intilize scracth_glyph to avoid + compose_glyph_string on it. + (get_gstring): Don't call compose_glyph_string on scracth_glyph. + (mdraw_coordinates_position): Fix previous change. + + * internal-gui.h (glyph_category): New enum. + (MGlyph): Change type of to enum glyph_category. + + * face.c (mface__realize): Delete args language and charset. + (mface__for_chars): Fix for the case that glyphs have different + rfaces. + (mface__update_frame_face): Adjust for mface__realize change. + + * face.h (mface__realize): Adjust prototype. + +2004-10-05 Kenichi Handa + + * language.c (mlang__init): Add Akan. + +2004-10-04 Kenichi Handa + + * font-ft.c (add_font_info): Add instead of push the element. + (ft_list_family): For generic fonts, try all + substituted. families. + + * font-flt.c (UPDATE_CLUSTER_RANGE): New macro. + (run_rule): Don't update cluster range here. + (run_command): Update cluster range on appending a glyph. + (run_otf): Update cluster range for glyphs generated by OTF. + +2004-10-02 Kenichi Handa + + * m17n-X.c (device_open): Handle Mfont key in PLIST. + +2004-09-30 Kenichi Handa + + * font-ft.c (ft_select): Ignore family on calling mfont__score. + +2004-09-30 Kenichi Handa + + * font.h: Include . + (MFTInfo): New member langset. + (mfont__encoding_list): Extern it. + + * font.c (mfont__encoding_list): New function. + (mdebug_dump_font_list): New function. + + * font-ft.c: Don't include here. + (Mserif, Msans_serif, Mmonospace, Mmedium, Mr, Mnull): New + variables. + (ft_family_list): New variable. + (set_font_info): New arg basep. Callers changed. + (fc_list): Check the return value of FcPatternGetString. + (add_font_info): New arg plist. Callers changed. Update + ft_family_list. + (ft_list_family): New function (merged fc_list and ft_list_all). + (ft_select): Use ft_list_family. + (ft_list): Likewise. If FONT is not NULL, check all fonts. Fix + typo (== -> !=). + (mfont__ft_init): Initialize above new variables. + (mfont__ft_fini): Free ft_family_list. + (STRDUP_LOWER): New macro. + (set_font_info): Use STRDUP_LOWER. + (ft_list_family): Avoid duplicate addition of font path. Use + STRDUP_LOWER. + (fc_decode_prop): Fix typo. + + * m17n-X.c (MDisplayInfo): New member all_fonts_scaned. + (xfont_registry_list): Change argument disp_info to frame. + Callers changed. + (xfont_list_all): New function. + (xfont_list): If FONT is not NULL, check all fonts. + +2004-09-28 Kenichi Handa + + * m17n-X.c (MXFont, MXFontList): New types. + (MDisplayInfo): Delete members font_registry_list, + iso8859_1_family_list, iso10646_1_family_list, new members + font_list, base_font_list. + (free_display_info): Adusted for the change of MDisplayInfo. + (xfont_driver): Initialize with xfont_list. + (font_compare): New function. + (build_font_list): Deleted. + (xfont_registry_list): New function. + (xfont_select): Use xfont_registry_list. + (xfont_list): New function. + (device_open): Adusted for the change of MDisplayInfo. + + * font-ft.c (add_font_info): New arg languages. Callers changed. + (fc_list): Get languages from fonts.. + (ft_list_all): Renamed from ft_list. Callers changed. + (ft_list): New function. + (mfont__ft_driver): Initalize with ft_list. + + * font.c (mfont_list): New function. + + * font.h (struct MFontDriver): New member `list'. + (MFTInfo): New member languages. + + * m17n-gui.h (mfont_list): Extern it. + +2004-09-27 Kenichi Handa + + * internal-gui.h (struct MGlyphString): Delete members mt, + sub_width, sub_lbrearing, sub_rbearing, and region. + + * draw.c (MSubTextExtents): New type. + (layout_glyphs): New arg extents. Set its members. + (layout_glyph_string): Adjusted for the above change. + (alloc_gstring): Don't set gstring->mt. + (truncate_gstring): Call line_break function with mt instead of + gstring->mt. + +2004-09-22 Kenichi Handa + + * mtext.c (count_utf_16_chars): Count each code of invalid + surrogates as one. + +2004-09-19 Kenichi Handa + + * mtext.c (default_utf_16, default_utf_32): Rename them to + MTEXT_FORMAT_UTF_16 and MTEXT_FORMAT_UTF_32 respectively. Caller + changed. + + * m17n-core.h (MTEXT_FORMAT_UTF_16, MTEXT_FORMAT_UTF_32): Extern + them. + +2004-09-13 Kenichi Handa + + * draw.c (Mlatin): Don't declare it here. + (visual_order): Fix reordering of combining characters. + (compose_glyph_string): Fix detection of script. + (layout_glyphs): Don't fix reordering of combining characters + here. + (layout_glyph_string): Pay attention to + control->disable_overlapping_adjustment. + (truncate_gstring): Include at least on character in a line. + (get_gstring): Always scan one full line. + (mdraw__init): Don't initialize Mlatin here. + (mdraw_text_per_char_extents): Fix iteration. If a glyph doesn't + have a font, use ascent/descent of an ASCII font. Allow + ink_array_return and logical_array_return to be NULL. + (mdraw_coordinates_position): Fix iteration. + + * font-ft.c (MFTtoProp): Member completely changed. + (ft_to_prop): Adjusted for the above change. + (ft_to_prop_size): Likewise. + (set_font_info): Adjusted for the change of MFTtoProp. + (fc_generic_family_list): New variable. + (fc_list): Add special handling of generic font names. + (mfont__ft_init): Adjusted for the change of MFTtoProp. + Initialize fc_generic_family_list. + (mfont__ft_fini): Don't free ft_to_prop. Free + fc_generic_family_list. + (FC_vs_M17N_font_prop): New type. + (fc_weight_table, fc_slant_table, fc_width_table): New variables. + (fc_decode_prop, fc_encode_prop): New functions. + (mfont__ft_parse_name): Use fc_decode_prop. + (mfont__ft_unparse_name): Use fc_encode_prop. + + * m17n-X.c (MDisplayInfo): Delete member realized_font_list. + (MWDevice): Add member realized_font_list. + (free_display_info): Don't free disp_info->realized_font_list. + (free_device): Free device->realized_fontset_list. + (xft_find_metric): Use gstring->frame instead of rfont->frame. + (device_open): Don't initialize disp_info->realized_font_list. + (device_open): Initialize device->realized_font_list and set it to + frame->realized_font_list. + + * fontset.c (try_font_group): New function. + (mfont__lookup_fontset): Use try_font_group. + + * font.c (common_weight): Change the order of "regular". + + * face.c (Mlatin): Don't make it static. + (mface__realize): Be sure to set work_gstring.frame. + (mface__for_chars): Likewise. + + * mtext.c (mdebug_dump_mtext): Fix for the case of mt->format > + MTEXT_FORMAT_UTF_8. + + * internal-gui.h (Mlatin): Extern it. + + * m17n-gui.h (MDrawControl): New member + disable_overlapping_adjustment. + +2004-09-06 Kenichi Handa + + * font-flt.c (run_otf): Fix typo ('}'->']'). + + * internal-gui.h (MAKE_PRECOMPUTED_COMBINDING_CODE) + (COMBINING_PRECOMPUTED_P): New macros. + + * draw.c (layout_glyphs): Handle precomputed combining code. + + * font-ft.c (mfont__ft_drive_otf): Set g->combining_code to a + precomupted combining code. + +2004-09-03 Kenichi Handa + + * font-ft.c (mfont__ft_drive_otf): Use malloc and free for + otf_gstring.glyphs. + +2004-08-27 Kenichi Handa + + * face.c (mface_put_prop): If the new value is the same as the + current one, don't increment frame->tick. + +2004-08-25 Kenichi Handa + + * fontset.c (mfontset): Initialize font_spec_list member. + (mfontset_copy): Load fontset if necessary. + + * m17n-gui.h (MDrawGlyphInfo): Change the member name 'this' to + 'metrics' to for C++. + + * draw.c (mdraw_glyph_info): Adjusted for the member name change + (this -> metics). + +2004-08-16 Kenichi Handa + + * Version 1.1.0 released. + +2004-08-13 Kenichi Handa + + * language.c (mlang__init): Add Dhivehi. + + * m17n-gui.c (Mx, Mfreetype): Delete it. + (m17n_init_win): Don't initialize Mx and Mfreetype here. + + * m17n-gui.h (Mfreetype, Mxft): Extern them. + (mfont_resize_ratio): Extern it. + (MDrawGlyphInfo): New member logical_width; + (MDrawGlyph): New type. + (mdraw_glyph_list): Prototype adjusted. + + * m17n-X.c (xfont_open): Set type and fontp members. + (xft_open): Likewise. + + * internal-gui.h (Mx, Mfreetype): Delete extern. + + * font.h (struct MRealizedFont): New member type and fontp. + + * font.c (mfont__init): Initialize Mx, Mfreetype, and Mxft. + (Mx, Mfreetype): Declare here. + (Mxft): New variable. + (mfont_resize_ratio): New function. + + * font-ft.c (ft_open): Set type and fontp members. + + * draw.c (mdraw_glyph_list): Argument type changed. Don't set + glyph_code member. + +2004-08-11 Kenichi Handa + + * font-ft.c (ft_find_metric): Call FT_Load_Glyph with + FT_LOAD_DEFAULT. + +2004-08-06 Kenichi Handa + + * font-ft.c (mfont__ft_drive_otf): Fix for the case that no GSUB + feature to apply. + + * font-flt.c (run_otf): Print debugging information if necessary. + +2004-08-05 Kenichi Handa + + * font-ft.c (mfont__ft_drive_otf): Fix sign of g->yoff. Support + positioning_type 5 and 6. Switch simplified. + +2004-08-04 Kenichi Handa + + * font-ft.c (mfont__ft_drive_otf): Call OTF_drive_gdef. + +2004-08-02 Kenichi Handa + + * font.c (mfont__score): If prop is MFONT_FOUNDRY or MFONT_FAMILY, + set val to 1 even if it is greater than 1. + + * fontset.c (mfontset_modify_entry): Fix handling of the arg `how'. + +2004-07-29 Kenichi Handa + + * font-flt.c (run_rule, run_command, mfont__flt_run): Print more + debugging information. + + * internal.h (MDEBUG_PRINT5): New macro. + + * draw.c (layout_glyphs): Don't combine a zero width glyph with + the previous one if the zero width glyph has left or right + padding. + +2004-07-26 Kenichi Handa + + * m17n-X.c (xft_render): Pay attention to members left_padding and + right_padding of MGlyph. + + * draw.c (visual_order): Allocate one more elements for arrays as + a workaround of fribidi bug. + (layout_glyphs): Fix previous change. Check MGlyph->combining_code + instead of MGlyph->bidi_sensitive. + (layout_glyph_string): Pay attentinon to + control->orientation_reversed when padding at the head or tail. + Fix adjustment of space glyph width. + (get_gstring): If cursor_width or cursor_bidi is changed, don't + use a cache. + + * font-ft.c (mfont__ft_drive_otf): Set MGlyph->combining_code + instead of MGlyph->bidi_sensitive. + + * internal-gui.h (MGlyph): Delete member bidi_sensitive. + +2004-07-26 Kenichi Handa + + * draw.c (visual_order): Don't treat combined glyphs specially. + (layout_glyphs): Don't get metrics glyphs that are already ready. + Pay attention to MGlyph->bidi_sensitive. Combine a glyph of zero + width with the previous one. + (draw_background): Fix bar cursor position on a r2l glyph. + + * font-flt.c (FontLayoutCmdOTF): Move back from internal-gui.h. + (run_rule): Fix place of updating cluster_begin_pos and + cluster_end_pos here. + (run_otf): Don't set left_padding. + + * font-ft.c (adjust_anchor): Type of argument `code' changed. + Caller changed. + (mfont__ft_drive_otf): Renamed back from mfont__ft_drive_gsub. + Fix handling of GPOS. + (mfont__ft_drive_gpos): Delete this function. + + * font.h (mfont__ft_drive_otf): Renamed back from + mfont__ft_drive_gsub. + (mfont__ft_drive_gpos): Delete extern. + + * internal-gui.h (FontLayoutCmdOTF): Move back to font-flt.c. + (MGlyph): Delete member otf_cmd, add member bidi_sensitive. + +2004-07-23 Kenichi Handa + + * draw.c (layout_glyphs): Call mfont__ft_drive_gpos with glyphs of + the same bidi level. + + * font-ft.c (mfont__ft_drive_gpos): Check bidi-level. + +2004-07-22 Kenichi Handa + + * font-flt.c (load_flt): Treat the symbol Mend as end-of-file. + +2004-07-20 Kenichi Handa + + * draw.c (render_glyphs): Fix checking of g->code validity. + + * face.c (mface__realize): Set g.type. + +2004-07-18 Kenichi Handa + + * Makefile.am: Prepend ${top_srcdir} to all *.la in + *_LIBADD/*_LDADD. + + * m17n-gui.c (mframe): Print error message give by dlopen to + stderr. + +2004-07-16 Kenichi Handa + + * draw.c (compose_glyph_string): Improve the way of deciding a + script. For a character that doesn't have script property, use + the last non-latin script. + + * font-ft.c (fc_list): Cancel previous change. + (mfont__ft_init): Add more entries in ft_to_prop_name. + +2004-07-15 Kenichi Handa + + * draw.c (mdraw_glyph_list): Add the width of padding glyphs to + previous or next character glyphs. + +2004-07-14 Kenichi Handa + + * draw.c (compose_glyph_string): Be sure to set codes for glyphs + of type GLYPH_SPACE. + + * fontset.c (mfont__lookup_fontset): If glyph type is + GLYPH_SPACE, get codes for SPACE. + + * internal-gui.h (Mfont): Delete extern. + + * m17n-gui.h (Mfont): Delete duplicated extern. + +2004-07-13 Kenichi Handa + + * font-ft.c (DEVICE_DELTA): New macro. + (adjust_anchor): New function. + (mfont__ft_drive_gsub): Renamed from mfont__ft_drive_otf. Drive + only GSUB. + (mfont__ft_drive_gpos): New function. + + * font-flt.c (FontLayoutCmdOTF): Moved to internal-gui.h. + (FontLayoutContext): Delete member `rfont'. + (run_otf): Set g->otf_cmd. Call + (mfont__flt_run): Don't set ctx.rfont. Call mfont__ft_decode_otf + only whne HAVE_OTF is defined. + + * fontset.c: Include "config.h". + + * internal-gui.h (FontLayoutCmdOTF): Moved from font-flt.c. + (MGlyph): New member otf_cmd. + + * font.h (mfont__ft_drive_gsub): Changed from mfont__ft_drive_otf. + (mfont__ft_drive_gpos): Extern it. + + * face.c: Include "config.h". + + * draw.c (layout_glyphs): Call mfont__ft_drive_gpos. + + * input-gui.c: Include "config.h". + + * plist.c: Include "config.h". + +2004-07-06 Kenichi Handa + + * m17n-gui.c, m17n-gui.h, m17n-gd.c, m17n-X.h, m17n-X.c, + internal-gui.h: Cancel previous changes. + + * m17n-gd.h: Delete it. + + * Makefile.am (libm17n_core_la_LIBADD): New variable. + (libm17n_core_la_LDFLAGS): Add -export-dynamic, move + @XML2_LD_FLAGS@ to above. + (libm17n_la_LIBADD): Add -ldl. + (libm17n_la_LDFLAGS): Add -export-dynamic. + (X_LD_FLAGS): Fix the order of linking. + (libm17n_gui_la_LIBADD): Add ${OPTIONAL_LD_FLAGS}. + (libm17n_gui_la_LDFLAGS): Add -export-dynamic, delete above. + (libm17n_X_la_LDFLAGS): Add -module. + (libm17n_gd_la_SOURCES): Delete m17n-gd.h. + (libm17n_gd_la_LIBADD): Add @GD_LD_FLAGS@. + (libm17n_gd_la_LDFLAGS): Add -module. + (include_HEADERS): Delete m17n-gd.h. + +2004-06-30 Kenichi Handa + + * m17n-gui.c: Adjusted for the change of struct MDeviceDriver. + (MDeviceLibraryInterface): Delete it. + (register_device_library): Delete it. + (m17n__device_library_list): Renamed from device_library_list. + + * m17n-gui.h (M17N_INIT_X, M17N_INIT_GD): New macros. + (m17n_init_win): Adjust prototype. + + * m17n-gd.c: Adjusted for the change of struct MDeviceDriver. + (m17n_init_gd): New function. + + * m17n-gd.h: New file. + + * m17n-X.h: Include . + (m17n_init_X): Extern it. + (M17N_INIT): Redefine it. + + * m17n-X.c: Adjusted for the change of struct MDeviceDriver. + (m17n_init_X): New function. + + * internal-gui.h (m17n__device_library_list): Extern it. + (struct MDeviceDriver): New members initialized, init, and fini. + + * Makefile.am (libm17n_X_la_LIBADD): Add ${X_LD_FLAGS} and + @XFT2_LD_FLAGS@. + (libm17n_X_la_LIBADD): Delete aboves. + (libm17n_gd_la_SOURCES): Add m17n-gd.h. + (libm17n_gd_la_LIBADD): Add @GD_LD_FLAGS@. + (libm17n_gd_la_LDFLAGS): Delete it. + (include_HEADERS): Add m17n-gd.h. + +2004-06-25 Kenichi Handa + + * Makefile.am (libm17n_X_la_LDFLAGS): Cancel previous change. + (libm17n_gd_la_LDFLAGS): Cancel previous change. + + * m17n-gd.c (gd_render): Don't call FT_Get_Char_Index. + + * font-ft.c (fc_list): If FcFontList finds no font, try + FcFontMatch. + + * draw.c (compose_glyph_string): Terminate the last loop after + doing default combining if necessary. + +2004-06-24 Kenichi Handa + + * draw.c (mdraw_glyph_list): Unref gstring->top at the tail. + + * character.c (mchar_define_property): Add const to an arg. + + * charset.c (mchar_define_charset): Add const to an arg. + + * coding.c (MCodingSystem): Add const to an arg or decoder. + (finish_decoding): Add const to an arg. + (decode_coding_charset, decode_coding_utf_8) + (decode_coding_utf_16, decode_coding_utf_32) + (decode_coding_iso_2022, decode_coding_sjis) + (mconv_define_coding): Likewise. + + * m17n-X.c (xft_find_metric): Delete unused variable. + + * m17n-core.h (mchar_define_property, mtext_from_data): Adjust + prototypes. + + * m17n.h (mchar_define_charset, mconv_define_coding): Adjust + prototypes. + + * mtext.c (count_utf_8_chars, count_utf_16_chars) + (mtext__from_data, mtext_from_data): Add `const' to an arg. + + * mtext.h (mtext__from_data): Ajust prototype. + +2004-06-23 Kenichi Handa + + * draw.c (compose_glyph_string): Always get glyph codes by + mface__for_char. + (mdraw_glyph_info): Set info->glyph_code and info->logical_width. + (mdraw_glyph_list): New function. + + * font-flt.c (mfont__flt_run): Be sure to call + rfont->driver->encode_char. + + * font-ft.c (ft_find_metric): Don't call FT_Get_Char_Index. + (ft_encode_char): Delete arg C. + (ft_render): Don't call FT_Get_Char_Index. + + * font.c (mfont__encodable_p): Delete it. + (mfont__encode_char): Be sure to call rfont->driver->encode_char. + + * font.h (struct MFontDriver): Delete arg C of encode_char. + (mfont__encodable_p): Delete extern. + + * m17n-X.c (xfont_encode_char): Delete arg C. + (xft_find_metric): Don't cal FT_Get_Char_Index. + (xft_render): Likewise. + + * m17n-gui.h (MDrawGlyphInfo): New members glyph_code and + logical_width. + (mdraw_glyph_list): Extern it. + + * Makefile.am (libm17n_X_la_LDFLAGS): Don't include ${X_LD_FLAGS}. + +2004-06-22 Kenichi Handa + + * m17n-gui.h (mfontset_lookup): Extern it. + + * m17n-gui.c (m17n_init_win): Delete unnecessary printing. + + * fontset.c (realize_fontset_elements) + (free_realized_fontset_elements, update_fontset_elements): New + functions. + (mfont__realize_fontset): Call realize_fontset_elements. + (mfont__free_realized_fontset): Call free_realized_fontset_elements. + (mfont__lookup_fontset): If a fontset was modified, update + the realized fontset. + (mfontset_modify_entry): Increment fontset->tick. + (mfontset_lookup): New function. + +2004-06-21 Kenichi Handa + + * font-ft.c (mfont__ft_parse_name): Cast the arg to FcNameParse. + + * mtext.c (mtext_dup, mtext_cat, mtext_ncat, mtext_cpy) + (mtext_ncpy, mtext_duplicate): Pay attention to the case that the + length of source text 0. + +2004-06-21 Kenichi Handa + + * mtext.c (INC_POSITION): Use CHAR_UNITS_BY_HEAD_UTF16. + (compare): Pay attention to format other than utf-8. + (copy): Delete this function. + (count_by_utf_8, count_by_utf_16, insert): New functions. + (count_utf_16_chars): Fix handling of a surrogate pair. + (find_char_forward, find_char_backward): Likewise. + (mtext__from_data): Delete unnecessary check. Fix number of + allocated bytes. + (mtext_from_data): Don't count items. + (mtext_ref_char): Optimize the code. + (mtext_set_char): Pay attention to format other than utf-8. + (mtext_cat_char): Likewise. + (mtext_dup): Don't call copy, instead do allocation here. + (mtext_cat): Call insert instead of copy. + (mtext_ncat): Likewise. + (mtext_cpy): Delete character at first and call insert instead of + copy. + (mtext_ncpy): Likewise. + (mtext_copy): Likewise. + (mtext_duplicate): Call insert instead of copy. + (mtext_del): Pay attention to format other than utf-8. + (mtext_ins): Simply call insert. + (mtext_ins_char): Pay attention to format other than utf-8. + (mtext_tok): Call insert instead of copy. + (mtext_text): Call UNIT_BYTES. + + * textprop.c (mtext__adjust_plist_for_change): New function. + + * character.h (USHORT_SIZE, UINT_SIZE, UNIT_BYTES): New macros. + (CHAR_UNITS_UTF16, CHAR_UNITS): Simplified. + (CHAR_UNITS_AT): Fix typo. + (CHAR_UNITS_BY_HEAD): Fix typo. + (STRING_CHAR_AND_UNITS): Fix typo. + + * internal.h (MTEXT_READ_ONLY_P): New macro. + + * mtext.h (mtext__replace): Delete the extern. + (mtext__adjust_foramt): Adjust prototype. + + * plist.c (mplist_deserialize): Adjust the format of MT to utf-8 + if possible. Otherwise make a copy of mmt. + + * coding.c (mconv_decode, mconv_gets): Adjust the format of MT to + utf-8. + +2004-06-18 Kenichi Handa + + * character.h (CHAR_STRING_UTF16): Fix syntax. + +2004-06-16 Kenichi Handa + + * Makefile.am (libm17n_gd_la_LIBADD): Delete it. + (libm17n_X_la_LIBADD): Delete it. + (libm17n_gd_la_LDFLAGS): Don't include @GD_LD_FLAGS@. + + * m17n-X.c (device_open): Add parens in `if' condition. + + * mtext.c (INC_POSITION): Handle format other than utf8 and utf16. + (DEC_POSITION): Likewise. + (compare): Fix case that mt1->format is MTEXT_FORMAT_UTF_8. + +2004-06-15 Kenichi Handa + + * fontset.c (mfont__lookup_fontset): Fix selection of font groups + by language. + + * draw.c (compose_glyph_string): If language is specified, call + mface__for_chars even if a text is all latin. Fix condition for + setting non_ascii_found. + + * m17n-X.c (xft_find_metric): Fix setting of g->lbrearing. + + * m17n.h (minput_char_to_key): Delete extern. + + * m17n-gui.h (minput_event_to_key): Cancel previous change. + + * m17n-gui.c (null_device_open): Set several members of frame. + +2004-06-14 Kenichi Handa + + * m17n-gui.h (minput_event_to_key): Delete extern. + + * symbol.h (struct MSymbolStruct): Renamed from MSymbol. + + * m17n-core.h (MSymbol): Defined as "struct MSymbolStruct *". + + * Makefile.am (AM_CPPFLAGS): Refer to @M17NDIR@. + +2004-06-08 Kenichi Handa + + * character.c (mchar_put_prop): Don't increment the ref-count of + record->table. + +2004-06-04 Kenichi Handa + + * m17n-core.c (mdebug__register_object): New function. + (mdebug__unregister_object): Likewise. + + * internal.h (mdebug__register_object, mdebug__unregister_object): + Extern them. + (M17N_OBJECT_REGISTER, M17N_OBJECT_UNREGISTER): Call them + respectively. + + * charset.c (mcharset__load_from_database): Don't call + mconv__register_charset_coding here. + + * coding.c (find_coding): Get a real name from an element of + coding_definition_list. + (mconv__register_charset_coding): Set the real name at the top of + param. + (mcoding__load_from_database): Likewise. + (mconv_list_codings): Adjusted for the above change. + +2004-06-03 Kenichi Handa + + * coding.c (find_coding): Find by canonicalized name. Don't have + to modify the element of coding_definition_list by + mplist__from_plist. + (mconv__define_coding_from_charset): Delete it. + (mconv__register_charset_coding): Canonicalize sym. + (mcoding__load_from_database): Register plist modified by + mplist__from_plist. + + * coding.h (mconv__define_coding_from_charset): Don't extern it. + + * font-ft.c (ft_open): Fix setting of rfont->descent. + +2004-06-02 Kenichi Handa + + * font.c (enum xlfd_field_idx): Moved from m17n-X.c. + (xlfd_parse_name): Merge split_font_name and xfont_parse_name. + (xlfd_unparse_name): Renamed from xfont_build_name. + (mfont__init): Initialized Mfontconfig. + (mfont__free_realized): Unconditionally unref rfont->info. + (mfont__select): Free `this' if it's not best. + (mfont__open): Don't check frame->realized_font_list. + (mfont__parse_name_into_font): New function. + (Mfontconfig): New variable. + (mfont_from_name): Call mfont_parse_name. + (mfont_name): Call mfont_unparse_name. + (mdebug_dump_font): Likewise. + + * font.h (struct MFontDriver): Delete members parse_name and + build_name. + (mfont__ft_parse_name, mfont__ft_unparse_name): Extern them. + (mfont__parse_name_into_font): Extern it. + + * font-ft.c: Include "symbol.h". + (close_ft): Unconditionally free filename and charmap_list of + ft_into. + (ft_open): Duplicate base->filename. Increment ref-count of + ft_info->charmap_list. Free ft_info->charmap_list and + ft_info->filename on error. + (mfont__ft_parse_name, mfont__ft_unparse_name): New functions. + + * m17n-X.c (xfont_driver): Don't include xfont_parse_name and + xfont_build_name. + (enum xlfd_field_idx): Moved to font.c. + (split_font_name, build_font_name): Likewise. + (build_font_list): Call mfont__parse_name_info_font. + (xfont_open): Call mfont__unparse_name. Free name. + (xfont_parse_name, xfont_build_name): Moved to font.c + (xft_select): Prototype deleted. + (device_open): Check HAVE_FREETYPE on using mfont__ft_driver. + Call mfont_pase_name. + + * m17n-gui.c (free_frame): Unref frame->font_driver_list. + (m17n_fini_win): Add check HAVE_FREETYPE on using null_interface. + (mframe): Likewise. + + * m17n-gui.h (mfont_parse_name, mfont_unparse_name, Mfontconfig): + Extern them. + + * Makefile.am (linkgui_LDADD): Add libm17n-X.la and libm17n-gd.la. + +2004-06-01 Kenichi Handa + + * fontset.c (mfontset_modify_entry): Pay attention to the case + that fontset->font_spec_list is NULL. + +2004-05-31 Kenichi Handa + + * m17n-gui.c: Include only when HAVE_DLFCN_H is defined. + + * input.c: Include only when HAVE_DLFCN_H is defined. + + * font.c (mfont__select): Print score the a font for debugging. + + * Makefile.am (libm17n_la_LIBADD): Delete -ldl. + + * coding.c (reset_coding_sjis): Check kanji and kana instead of + kanji_sym and kana_sym. + +2004-05-28 Kenichi Handa + + * Makefile.am (VINFO): New variable. + (libm17n_core_la_LDFLAGS, libm17n_la_LDFLAGS) + (libm17n_gd_la_LDFLAGS): Include ${VINFO}. + +2004-05-27 Kenichi Handa + + The following chanages are to make device dependent functions + accessible only from MDeviceDriver structure, and to add GD and + null device drivers. Font drivers get also device dependent. + + * m17n.c (m17n_init): Increament shell_initialized. + (m17n_fini): Decremented shell_initialized. + + * m17n-misc.h (enum MErrorCode): New element MERROR_GD. + + * m17n-gui.h (Mdevice, Mdisplay, Mscreen, Mdrawable, Mdepth) + (Mwidget, Mcolormap, Mx): Extern them. + + * m17n-gui.c: Include and "config.h". + (free_frame): Call frame->driver->close instead of + mwin__close_device. + (DLOPEN_SHLIB_EXT): New macro. + (MDeviceLibraryInterface): New type. + (device_library_list): New variable. + (register_device_library): New function. + (null_device): New variable. + (null_device_close, null_device_get_prop) + (null_device_realize_face, null_device_free_realized_face): New + function. + (null_driver): New variable. + (null_device_init, null_device_fini, null_device_open): New + functions. + (null_interface): New variable. + (Mfreetype, Mdevice): Declare them. + (m17n_init_win): Increment win_initialized. Initialize Mx, Mgd, + Mfreetype, Mdevice, Mdisplay, Mscreen, Mdrawable, Mdevice, and + Mwin__Close_Device. Register drivers for Mx and Mgd. + (m17n_fini_win): Decremented win_initialized. Call "fini" + function of all opened devices. Don't call mwin__fini. + (Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap): + Declare them here. + (mframe): Handle Mdevice key of PLIST. + (mframe_get_prop): Call frame->device->get_prop instead of + mwin__device_get_prop. + + * m17n-gd.c: New file. + + * m17n-core.h (M17NLIB_MAJOR_VERSION, M17NLIB_MINOR_VERSION) + (M17NLIB_PATCH_LEVEL, M17NLIB_VERSION_NAME): Updated to 1.1.0. + + * m17n-core.c (m17n_init_core): Increate core_initialized. + (m17n_fini_core): Decremented core_initialized. + + * m17n-X.h (Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget) + (Mcolormap): Don't extern them here. + + * m17n-X.c (FRAME_DEVICE): New macro. + (FRAME_DISPLAY, FRAME_SCREEN, FRAME_CMAP): Use FRAME_DEVICE. + (free_display_info): Use MPLIST_DO. + (free_device): Free rface->info. + (xft_close): Delete it. + (device_init): Renamed from mwin__init. + (device_fini): Renamed from mwin__fini. + (device_open): Renamed from mwin__open_device. + (x_driver): New variable. + (MXFontInfo): Delete member frame, add member display. + (Mdisplay, Mscreen, Mdrawable, Mdepth, Mwidget, Mcolormap, Mxim): + Don't declare them here. + + * internal-gui.h (MDeviceType): New enum. + (MWDefice): Delete it. + (struct MFrame): Change type of device to void *. New members + device_type, driver, font_driver_list. + (M_CHECK_WRITABLE, M_CHECK_READABLE): New macros. + (MDeviceDriver): New type. + (Mx, Mgd, Mfreetype): Extern them. + (mwin__XXX): Delete all of them. + + * input-gui.c (win_create_ic): Call frame->driver->XXX instead of + mwin__XXX. + (win_destroy_ic): Likewise. + (adjust_window_and_draw): Likewise. + (win_callback): Likewise. + (Mxim): Declare it here. + (minput_event_to_key): Call M_CHECK_READABLE. + + * fontset.c (mfont__lookup_fontset): Delete local variable + font_group. + + * font.h (struct MFontDriver): Delete member close, add members + parse_name and build_name. + (mfont__driver_list): Delete extern. + (mfont__close): Delete extern. + + * font.c (mfont__init): Don't set mfont__driver_list. + (mfont__fini): Don't unref mfont__driver_list. + (mfont__select): Try font drivers in frame->font_driver_list. Set + driver member of a realized font. + (mfont__close): Delete it. + (mfont_from_name, mfont_name, mdebug_dump_font): Call driver + functions of the default frame. + + * font-ft.c (close_ft): Check ft_info->ft_face and work + differently. + (add_font_info): Allocate ft_info by M17N_OBJECT. + (ft_close): Delete it. + (mfont__ft_driver): Don't set ft_close. + (ft_select): Increment ref-count of best_font. + (ft_open): Decremented ref-count of base. On error, call + FT_Done_Face and free ft_info. + (ft_find_metric): Always use XXX_MONO in load_flags. + (ft_render): Fix setting of width. Call + frame->driver->draw_points instead of mwin__draw_points. + (ft_to_prop): Don't set mfont__driver_list. + (mfont__ft_fini): Just unref ft_info. + + * face.c (mface__init): Exchange foreground and background of + mface__default. Call mface_put_prop to set hline of + mface_underline, + (mface__realize): Call frame->driver->XXX instead of mwin__XXX. + (mface__free_realized): Don't call mwin__free_realized_face. + + * draw.c (Mdepth): Don't declare it here. + (draw_background): Call frame->driver->XXX instead of mwin__XXX. + (render_glyphs, render_glyph_string): Likewise. + (mdraw__init): Don't set Mdepth. + (mdraw_text, mdraw_image_text, mdraw_text_with_control): Call + M_CHECK_WRITABLE. + (mdraw_text_per_char_extents): Return 0 on success and -1 on + error. + (mdraw_text_items): Check FRAME is writable. + (mdraw_per_char_extents): Implement body. + + * Makefile.am (lib_LTLIBRARIES): Include libm17n-gui.la and + libm17n-gd.la. + (OPTIONAL_LD_FLAGS): Include @FONTCONFIG_LD_FLAGS@. + (GUI_SOURCES): Delete it. + (libm17n_X_la_SOURCES): Don't include ${GUI_SOURCES}. + (libm17n_gui_la_SOURCES, libm17n_gui_la_LIBADD) + (libm17n_gui_la_LDFLAGS, libm17n_gd_la_SOURCES) + (libm17n_gd_la_LIBADD, libm17n_gd_la_LDFLAGS): New targets. + (linkgui_LDADD): Set to libm17n-gui.la + (linkgui_LDFLAGS): New target. + (SRC): Include ${libm17n_gui_la_SOURCES} and + ${libm17n_gd_la_SOURCES}. + +2004-05-24 Kenichi Handa + + * draw.c (draw_background): Don't draw background even if + rface->face.property[MFACE_BACKGROUND] is not Mnil. + +2004-05-22 Kenichi Handa + + * m17n-X.c (xft_open_font): Fix anti_alias setting. + +2004-05-20 Kenichi Handa + + * m17n-gui.h (MFaceHookFunc): Change this function type to void. + + * m17n-gui.c: Include "plist.h". + (mframe): If PLIST is NULL, initialize it to emply plist. + + * m17n-X.c (build_font_list): Don't set property[MFONT_TYPE]. + (xft_driver): New variable. + (xft_select, close_xft, xft_open_font, xft_open, xft_close) + (xft_find_metric, xft_render): New function. + (mwin__init): Adjusted for the new mfont__driver_list. + (mwin__open_device): Assume arg PARAM is not NULL. Push a newly + generated face to PARAM. + (mwin__realize_face): Fix setting of box colors. Don't call hook + function here. + (mwin__draw_hline): New function. + (mwin__xft_close, mwin__xft_open, mwin__xft_get_metric) + (mwin__xft_render): Delete these function. + + * internal-gui.h (struct MFrame): New member tick. + (struct MGlyphString): New member tick. + (mwin__draw_rect, mwin__draw_empty_boxes): Extern them. + (mwin__xft_open, mwin__xft_close, mwin__xft_get_metric) + (mwin__xft_render): Delete extern. + + * fontset.c (mfont__lookup_fontset): Make the code simpler. + (mfontset): Always increment the reference count of returned + object. + + * font-ft.c (mfont__ft_fini): Don't include here. + (MFTInfo): Moved to font.h. + (ft_iso8859_1_font_list): Delete this variable. + (set_font_info): Don't set font->property[MFONT_TYPE]. + (set_font_info): Don't udpate ft_iso8859_1_font_list. + (add_font_info): Change type to void. + (fc_list): Change anme from xft_list. Caller changed. Include + FC_FOUNDRY and FC_PIXEL_SIZE in FcObjectSet. + (mfont__ft_driver): Change name from ft_driver. Caller changed. + (ft_select): Check HAVE_FONTCONFIG instead of HAVE_XFT2. + (close_ft): Don't call mwin__xft_close. Unref + ft_info->extra_info. + (ft_open): Don't setup ft_info->fontname. Don't call + mwin__xft_open. + (ft_find_metric): Don't call mwin__xft_get_metric. + (ft_encode_char): Call rfont->driver->open instead of ft_open. + (ft_render): Don't check HAVE_XFT2. Don't call mwin__xft_render. + (mfont__ft_init): Adjusted for new mfont__driver_list. + (mfont__ft_fini): Don't unref ft_iso8859_1_font_list. + + * font.c (mfont__driver_list): Make it MPlist. + (mfont__init): Adjust initialization of mfont__driver_list. + (mfont__fini): Free mfont__driver_list. + (mfont__set_spec_from_face): Don't set spec->property[MFONT_TYPE]. + (mfont__select): Adjusted for the new mfont__driver_list. + + * font.h (enum MFontProperty): Delete MFONT_TYPE. + (mfont__drirver_list): Adjust prototype. + (MFTInfo): Move to here from fron.c. Deleve member fontname. + + * face.h (struct MFace): Delete member realized_face_list, add + member frame_list. + (struct MRealizedFace): Delete member need_update + andnofont_rface, add member non_ascii_list. + (mface__update_frame_face): Extern it. + + * face.c (hline_prop_list, box_prop_list, noop_hook): New + variables. + (get_hline_create, get_box_create): New functions. + (find_realized_face): Cancel previous change. Arg RFONT deleted. + Use memcmp. + (free_face): Cancep previous change. Free face->frame_list. + (serialize_hline): Do nothing if hline->width is zero. + (serialize_box): Do nothing if box->width is zero. + (mface__init): Setup all properties of mface__default. + (mface__fini): Free hline_prop_list and box_prop_list. + (mface__realize): Cancel previous change. Update + face->frame_list. Setup rface->non_ascii_list. + (mface__for_chars): Update rface->non_ascii_list. + (mface__free_realized): Free rface->non_ascii_list. + (mface__update_frame_face): New function. + (mface): Initialize face->frame_list. + (mface_copy): Likewise. Just copy MFACE_HLINE and MFACE_BOX + properties. + (mface_merge): Likewise. + (mface_put_prop): If key is Mhline or Mbox, get value by + get_hline_create or get_box_create respectively. + (mface_put_prop): Update frame->tick and call + mface__update_frame_face if necessary. + (mface_update): Do nothing if func is noop_hook. + + * draw.c (render_glyphs): If a font is not found, use + mwin__draw_empty_boxes. + (alloc_gstring): Initialize gstring->tick. + (get_gstring): Check gstring->tick. + +2004-05-17 Kenichi Handa + + * face.c (find_realized_face): Return value changed. If RFONT is + NULL, avoid unnecessary checking. + (free_face): Free face->realized_face_list. + (mface__realize): Adjusted for the change of find_realized_face. + If it returns a realized face that needs update, free it and + realize a new one. Push a new realized face to + frame->realized_face_list instead of appending. + (mface__for_chars): Adjusted for the change of find_realized_face. + Short cut if the required font is in rface->ascii_rface. + (mface_put_prop): Free old value if necessary. Set need_update + member of realized faces to 1. + + * face.h (struct MFace): Delete member tick, add member + realized_face_list. + (struct MRealizedFace): Delete member tick, add member + need_update. + +2004-05-13 Kenichi Handa + + * m17n-X.c (mwin__xft_open): Destroy unnecessary patterns. + +2004-05-12 Kenichi Handa + + * internal-gui.h (mwin__xft_open): Arguemnt name changed. + + * m17n-X.c (mwin__xft_open): Argument changed to fontname and + parse it XftNameParse. + + * font-ft.c (MFTInfo) [HAVE_XFT2]: New member fontname. + (all_fonts_scaned): New variable. + (set_font_info): FAMILY may be Mnil. + (add_font_info): Argument changed. + (xft_list): Call add_font_info in it. + (ft_list): Likewise. + (ft_select): Make it work in the case family is Mnil. + (ft_open) [HAVE_XFT2]: Setup ft_info->fontname. + (mfont__ft_fini): Set all_fonts_scaned to 0. + + * fontset.c (mfont__lookup_fontset): Don't repeatedly try a font + that is failed to open. + +2004-05-10 Kenichi Handa + + * m17n-X.c (mwin__xft_render): Don't use anti-alias if the + device's depth is 1 (i.e. monochrome). + + * Makefile.am (OPTIONAL_LD_FLAGS): Change the order of elements + to work around the problem of libtool. + + * font-ft.c: Include . + (Municode_bmp, Municode_full, Miso10646_1, Miso8859_1): New + variables. + (mfont__ft_init): Initialize them. + (ft_iso8859_1_font_list): New variable. + (set_font_info): Detect a font containing iso8859-1 glyphs and + register it in ft_iso8859_1_font_list. If the font is not + scalable, assume it as BDF or PCF font and setup SIZE and RESY + properties of the font from its properties. + (add_font_list): If the font is not scalable, check if it is BDF + or PCF font. If not, ignore it. + (ft_select): If FAMILY is Mnil, return NULL only if the requested + registry is not iso8859-1. + (ft_select) [not HAVE_XFT2]: If FAMILY is Mnil, select one from + ft_iso8859_1_font_list. + (ft_find_metric): If the font is not scalable, assume it as BDF + or PCF, and get a metric from its properties. + (mfont__ft_fini): Free ft_iso8859_1_font_list. + +2004-05-07 Kenichi Handa + + * Makefile.am (libm17n_la_LIBADD): Include -ldl. + (libm17n_la_LDFLAGS): Delete it. + (noinst_PROGRAMS): Renamed from bin_PROGRAMS. + (install-binPROGRAMS, uninstall-binPROGRAMS): Delete them. + +2004-05-06 Kenichi Handa + + * draw.c (compose_glyph_string): Fix previous change. + +2004-04-30 Kenichi Handa + + * font-ft.c (ft_list): Delete unused variable `result'. + (ft_render): Fix for the case that bitmap.pitch < bitmap.width. + +2004-04-27 Kenichi Handa + + * m17n-X.c: Include config.h + [HAVE_XFT2]: Include . + (GCInfo) [HAVE_XFT2]: New member xft_color_fore, xft_color_back. + (MWDevice) [HAVE_XFT2]: New member xft_draw. + (FRAME_CMAP, FRAME_VISUAL): New macros. + (free_device) [HAVE_XFT2]: Destroy device->xft_draw. + (xfont_driver): Make it static. + (mwin__open_device) [HAVE_XFT2]: Setup device->xft_draw. + (mwin__realize_face) [HAVE_XFT2]: Setup info->xft_color_fore and + info->xft_color_back. + (MXftFontInfo) [HAVE_XFT2]: New type. + (mwin__xft_close) [HAVE_XFT2]: New function. + (mwin__xft_open) [HAVE_XFT2]: New function. + (mwin__xft_get_metric) [HAVE_XFT2]: New function. + (mwin__xft_render) [HAVE_XFT2]: New function. + + * internal-gui.h [HAVE_FREETYPE]: Include FT_FREETYPE_H. + (mwin__xft_open, mwin__xft_close) [HAVE_FREETYPE]: New externs. + (mwin__xft_get_metric, mwin__xft_render) [HAVE_FREETYPE]: New + externs. + + * font.h [HAVE_FREETYPE]: Include FT_FREETYPE_H. + + * font-ft.c: Don't include FT_FREETYPE_H here. + [HAVE_XFT2]: Include . + (fontconfig_initialized, fc_config) [HAVE_XFT2]: New variables. + (MFTInfo): New member charmap_index. + (MFTInfo) [HAVE_XFT2]: New member xft_info. + (check_otf_filename): Renamed from check_filename. Return value + changed. + (ft_set_property): This function deleted. + (set_font_info): New function. + (add_font_list): Argument changed. Add multiple fonts. + (xft_list) [HAVE_XFT2]: New function. + (ft_list) [not HAVE_XFT2]: New function. + (ft_select): Add code for Xft. + (close_ft): Likewise. + (ft_open): Likewise. + (ft_find_metric): Likewise. + (ft_encode_char): Likewise. + (ft_render): Likewise. + + * makefile.am (OPTIONAL_LD_FLAGS): Include @XFT2_LD_FLAGS@. + +2004-04-26 Kenichi Handa + + * textprop.c (mtext_attach_property): Declare the return type as + `int'. + +2004-04-21 Kenichi Handa + + * Makefile.am (OPTIONAL_LD_FLAGS): Include @XFT2_LD_FLAGS@ + +2004-04-09 Kenichi Handa + + * font-flt.c (struct): New members seq_beg, seq_end, seq_from, + seq_to. + (load_command): Setup above members. + +2004-04-05 Kenichi Handa + + * m17n-X.c (xfont_encode_char): Fix checking of byte1 and byte2. + +2004-03-30 Kenichi Handa + + * m17n-X.c (xfont_encode_char): Return MCHAR_INVALID_CODE if code + >= 0x10000. + + * m17n-core.h (M17NLIB_PATCH_LEVEL): Changed to 2. + (M17NLIB_VERSION_NAME): Changed to 1.0.2. + +2004-03-29 Kenichi Handa + + * Version 1.0 Patch Level 2 released. + +2004-03-29 Kenichi Handa + + * charset.c (make_charset): Set charset->fully_loaded and + charset->simple correctly. Don't try to get charset->min_char and + charset->max_char for a charset of method subset and superset. + Don't load a mapping file here. + (mcharset__init): Set unified_max. + (mcharset__load_from_database): Free a working plist. + + * coding.c (mcoding__fini): Free all malloced data. + + * input-gui.c (win_create_ic): Set control.as_image for preediting + to 0. + + * internal.h (M17N_OBJECT_REGISTER): Check the member `used' (not + `count') to initialize the array. + + * locale.c (mlocale_set): Fix the order of M17N_OBJECT_REF and + M17N_OBJECT_UNREF. + + * m17n-X.c (xfont_render): If rface->rfont is null, draw a + rectangle. + (mwin__create_window): Fix bug of setting a background pixel of a + new window. + (mwin__adjust_window): Clear the window before drawing. + + * m17n-core.c (mdebug__report_object): Free array->objectes if + necessary. + (m17n_init_core): Don't set report_header_printed to 0 here. + Fix debugging information. + (m17n_fini_core): Set report_header_printed to 0 here. + + * m17n-core.h (mplist_deserialize): Extern it. + + * m17n-gui.c (m17n_fini_win): Fix debugging information. + + * m17n.c (m17n_fini): Fix debugging information. + + * mtext.c (mtext__adjust_foramt): New function. + + * mtext.h (mtext__adjust_foramt): Extern it. + + * plist.c (mplist_deserialize): Renamed from mplist__deserialize. + + * plist.h (mplist__deserialize): Don't extern it. + + * symbol.c (msymbol__fini): Set freed_symbols to 0. Set all + elements of symbol_table to NULL. Report about created and freed + symbols if MDEBUG_FINI is set. + +2004-03-22 Kenichi Handa + + * m17n-core.c (m17n_init_core): Set merror_code to MERROR_NONE. + + * m17n.c (m17n_init): Fix the way of checking merror_code. + + * m17n-gui.c (m17n_init_win): Fix the way of checking merror_code. + +2004-03-22 Kenichi Handa + + * fontset.c (realize_font_group): Adjust the font size by + mfont__resize before selecting a font. + + * font-ft.c (mfont__ft_init): Add oblique and boldoblique. + +2004-03-19 Kenichi Handa + + * Version 1.0 Patch Level 1 released. + +2004-03-19 Kenichi Handa + + * m17n-core.h (M17NLIB_PATCH_LEVEL): New macro. + + * m17n-core.c (M17NLIB_PATCH_LEVEL): Describe it. + +2004-03-19 Kenichi Handa + + Re-apply the changes forgotten in the released version. + + * charset.c (mcharset__load_from_database): Call + mchar_define_charset. + + * coding.c (encode_unsupporeted_char): Put Mcoding text property. + (mconv_encode_range): Put Mcoding text property. + +2004-03-18 Kenichi Handa + + * draw.c (Mdepth): New variable. + (visual_order): Delete unused local var `pos'. + (compose_glyph_string): Fix for the case that gstring->glyphs is + realloced. Stop generating glyphs at TO. Fix handling of + control charaters. + (layout_glyphs): Get metrics of all glyphs in advance. Set + lbearing and rbearing of base of composition glyph correctly. + Handle left-overhang glyphs correctly. + (alloc_gstring): New arg frame. Set gstring->anti_alias. Caller + changed. + (dump_combining_code): Change the defualt off_x character to ".". + (mdraw__init): Initialize Mdepth. + + * face.c (work_gstring): New variable + (mface__init): Initialize work_gstring. + (mface__fini): Free work_gstring.glyphs. + (mface__realize): Don't handle videomode property here. Adjusted + for the change of mfont__get_metric. + (mface__for_chars): Adjusted for the change of mfont__get_metric. + + * face.h (enum face_gc): Moved to m17n-X.c. + + * font.h (struct MFontDriver): Arguments of find_metric changed. + (mfont__select): Prototype adjusted. + (mfont__get_metric): Likewise. + (mfont__ft_drive_otf): Likewise. + (mfont__flt_run): Likewise. + + * font.c (mfont__select): New argument layouter. If layouter is + different in the registered font, make a new copy of realized + font. + (mfont__get_metric): Argument changed. Get metrics of multiple + glyphs. + (mfont_find): Call mfont__select with layouter as Mnil. + + * font-flt.c (FontLayoutContext): New member rfont. + (run_otf): Adjusted for the change of mfont__ft_drive_otf. + (mfont__flt_run): Argument changed. Initialize ctx.rfont. + + * font-ft.c (ft_find_metric): Arguments changed. Get metrics of + multiple glyphs. + (NUM_POINTS): New macro. + (MPointTable): New type. + (ft_render): Use mwin__draw_points instead of mwin__draw_bitmap. + (mfont__ft_drive_otf): New argument rfont. + + * fontset.c (realize_font_group): Adjusted for the changed of + mfont__select. + (check_fontset_element): This function deleted. + + * input-gui.c (adjust_window_and_draw): Locate a preedit window + off the parent window if the preedit text is zero length. + + * internal-gui.h (struct MFrame): New members foreground, + background, videomode, font. + (struct MGlyphString): New member anti_alias. + (MDrawPoint): New type. + (mwin__draw_bitmap): Prototype deleted. + (mwin__draw_points): Prototype added. + + * m17n-gui.h (MDrawControl): New member anti_alias. + + * m17n-gui.c (free_frame): Free frame->font. + (mframe): Set the fontset of frame->face to the default fontset. + + * m17n-X.c (RGB_GC): New type. + (enum gc_index): Renamed from enum face_gc. Member names changed. + (GCInfo): New typel + (struct MWDevice): Members foreground and background deleted. New + member scratch_gc, gc_list. + (DEFAULT_FONT, FALLBACK_FONT): New macros. + (free_device): Free GCs in device->gc_list. + (get_rgb_gc): New function. + (get_gc): Renamed and argument changed from get_color. + (get_gc_for_anti_alias): New function. + (xfont_find_metric): Arguments changed. Get metrics of multiple + glyphs. + (set_region): Argument changed. Caller changed. + (xfont_render): Allways set a font in gc. + (x_error_handler, x_io_error_handler): Define only if + X_SET_ERROR_HANDLER is defined. + (mwin__open_device): Create device->scratch_gc. Set members + foreground, background, and videomode of frame. Call + XSetErrorHandler and XSetIOErrorHandler only if + X_SET_ERROR_HANDLER is defined. + (struct gc_list): Deleted. + (REGISTER_GC, UNREGISTER_GC): These macros deleted. + (mwin__realize_face): Adjusted for the change of the format of + rface->info and the charge of set_region. + (mwin__free_realized_face, mwin__fill_space, mwin__draw_hline) + (mwin__draw_box): Likewise. + (mwin__draw_bitmap): This function deleted. + (mwin__draw_points): New function. + (mwin__verify_region): Adjusted for the change of the format of + rface->info and the charge of set_region. + (mwin__create_window): Inherit backgound pixel from parent. + (mwin__dump_gc): Adjusted for the change of the format of + rface->info. + +2004-03-16 Kenichi Handa + + * m17n-X.c (mwin__parse_event): Fix handling of modifier keys. + + * input.c (M_key_alias): New variable. + (handle_key): Try M_key_alias property of a key too. + (minput__init): Initialize M_key_alias. Give that property to + symbols in one_char_symbol. Fix bug of initializing + one_char_symbol. + + * draw.c (compose_glyph_string): Don't handle + ignore_formatting_char here. Include formatting characters in the + range processed by a FTL. + (layout_glyph_string): Handle ignore_formatting_char here. + +2004-03-12 Kenichi Handa + + * input-gui.c (win_create_ic): Enable bidi in status control. + + * draw.c (visual_order): Avoid re-ordering of combining glyphs only. + +2004-03-09 Kenichi Handa + + * input.c (load_input_method): If title is not specified, use the + input method name as title. + + * m17n-X.c (get_color): Make it static. + (xim_create_ic, xim_destroy_ic, x_error_handler) + (x_io_error_handler): Likewise. + +2004-03-01 Kenichi Handa + + * Version 1.0 released. + + +Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + 2013, 2014 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + +This file is part of the m17n library. + +The m17n 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 m17n 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 m17n library; if not, write to the Free +Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..563de14 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,134 @@ +# Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011, 2012 +# National Institute of Advanced Industrial Science and Technology (AIST) +# Registration Number H15PRO112 + +# This file is part of the m17n library. + +# The m17n 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 m17n 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 m17n library; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +VINFO = -version-info @API_VERSION@ + +BASICBUILDS = libm17n-core.la libm17n.la libm17n-flt.la +if WITH_GUI +BUILD_LIBS = $(BASICBUILDS) libm17n-gui.la +else +BUILD_LIBS = $(BASICBUILDS) +endif + +lib_LTLIBRARIES = $(BUILD_LIBS) + +libm17n_core_la_SOURCES = \ + character.h character.c \ + chartab.h chartab.c \ + database.h database.c \ + internal.h \ + plist.h plist.c \ + m17n-core.h m17n-core.c \ + m17n-misc.h \ + mtext.h mtext.c \ + symbol.h symbol.c \ + textprop.h textprop.c \ + mtext-lbrk.c mtext-wseg.c + +libm17n_core_la_LIBADD = @XML2_LD_FLAGS@ @THAI_WORDSEG_LD_FLAGS@ +libm17n_core_la_LDFLAGS = -export-dynamic ${VINFO} + +libm17n_la_SOURCES = \ + charset.h charset.c \ + coding.h coding.c \ + input.h input.c \ + language.h language.c \ + mlocale.h locale.c \ + m17n.h m17n.c +libm17n_la_LIBADD = ${top_builddir}/src/libm17n-core.la -ldl +libm17n_la_LDFLAGS = -export-dynamic ${VINFO} + +FLT_SOURCES = \ + internal-flt.h \ + m17n-flt.h m17n-flt.c + +libm17n_flt_la_SOURCES = ${FLT_SOURCES} +libm17n_flt_la_LIBADD = ${top_builddir}/src/libm17n-core.la +libm17n_flt_la_LDFLAGS = -export-dynamic ${VINFO} + +GUI_SOURCES = \ + face.h face.c \ + font.h font.c font-ft.c \ + fontset.h fontset.c \ + draw.c \ + input-gui.c \ + internal-gui.h \ + m17n-gui.h m17n-gui.c + +OPTIONAL_LD_FLAGS = \ + @FREETYPE_LD_FLAGS@ \ + @FRIBIDI_LD_FLAGS@ \ + @OTF_LD_FLAGS@ \ + @FONTCONFIG_LD_FLAGS@ + +libm17n_gui_la_SOURCES = ${GUI_SOURCES} +libm17n_gui_la_LIBADD = ${OPTIONAL_LD_FLAGS} ${top_builddir}/src/libm17n-core.la ${top_builddir}/src/libm17n.la ${top_builddir}/src/libm17n-flt.la +libm17n_gui_la_LDFLAGS = -export-dynamic ${VINFO} + +if WITH_GUI + +moduledir = ${libdir}/@M17N_MODULE_DIR@ +module_LTLIBRARIES = libm17n-X.la libm17n-gd.la +X_LD_FLAGS = ${X_PRE_LIBS} ${X_LIBS} @X11_LD_FLAGS@ ${X_EXTRA_LIBS} + +libm17n_X_la_SOURCES = m17n-X.h m17n-X.c +libm17n_X_la_LIBADD = ${X_LD_FLAGS} @XFT2_LD_FLAGS@ @FONTCONFIG_LD_FLAGS@ ${top_builddir}/src/libm17n-core.la ${top_builddir}/src/libm17n.la ${top_builddir}/src/libm17n-flt.la ${top_builddir}/src/libm17n-gui.la +libm17n_X_la_LDFLAGS = -avoid-version -module + +libm17n_gd_la_SOURCES = m17n-gd.c +libm17n_gd_la_LIBADD = @GD_LD_FLAGS@ @FREETYPE_LD_FLAGS@ ${top_builddir}/src/libm17n-core.la ${top_builddir}/src/libm17n.la ${top_builddir}/src/libm17n-flt.la ${top_builddir}/src/libm17n-gui.la +libm17n_gd_la_LDFLAGS = -avoid-version -module + +endif + +AM_CPPFLAGS = -DM17NDIR=\"@M17NDIR@\" -DM17N_MODULE_DIR=\"${libdir}/@M17N_MODULE_DIR@\" -DGETTEXTDIR=\"@GETTEXTDIR@\" + +BASICHEADERS = m17n-core.h m17n.h m17n-misc.h m17n-flt.h +if WITH_GUI +include_HEADERS = $(BASICHEADERS) m17n-gui.h m17n-X.h +else +include_HEADERS = $(BASICHEADERS) +endif + +SRC = ${libm17n_core_la_SOURCES} \ + ${libm17n_la_SOURCES} \ + ${libm17n_gui_la_SOURCES} \ + ${libm17n_X_la_SOURCES} \ + ${libm17n_gd_la_SOURCES} + +TAGS: ${SRC} + etags ${SRC} + +if MAINTAINER_MODE +noinst_PROGRAMS = linkcore linkshell linkgui + +linkcore_SOURCES = linkcore.c +linkcore_LDADD = ${top_builddir}/src/libm17n-core.la +linkcore_LDFLAGS = -static + +linkshell_SOURCES = linkshell.c +linkshell_LDADD = ${top_builddir}/src/libm17n.la +linkshell_LDFLAGS = -static + +linkgui_SOURCES = linkgui.c +linkgui_LDADD = ${top_builddir}/src/libm17n-gui.la +linkgui_LDFLAGS = -static +endif diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..e631c72 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,1078 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in 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. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011, 2012 +# National Institute of Advanced Industrial Science and Technology (AIST) +# Registration Number H15PRO112 + +# This file is part of the m17n library. + +# The m17n 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 m17n 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 m17n library; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@MAINTAINER_MODE_TRUE@noinst_PROGRAMS = linkcore$(EXEEXT) \ +@MAINTAINER_MODE_TRUE@ linkshell$(EXEEXT) linkgui$(EXEEXT) +subdir = src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc2.m4 \ + $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intdiv0.m4 $(top_srcdir)/m4/intl.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intmax.m4 \ + $(top_srcdir)/m4/inttypes-pri.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/lcmessage.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/lock.m4 $(top_srcdir)/m4/longlong.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/printf-posix.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/visibility.m4 \ + $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \ + $(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__include_HEADERS_DIST) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(moduledir)" \ + "$(DESTDIR)$(includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) $(module_LTLIBRARIES) +am__DEPENDENCIES_1 = +@WITH_GUI_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \ +@WITH_GUI_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +@WITH_GUI_TRUE@libm17n_X_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \ +@WITH_GUI_TRUE@ ${top_builddir}/src/libm17n-core.la \ +@WITH_GUI_TRUE@ ${top_builddir}/src/libm17n.la \ +@WITH_GUI_TRUE@ ${top_builddir}/src/libm17n-flt.la \ +@WITH_GUI_TRUE@ ${top_builddir}/src/libm17n-gui.la +am__libm17n_X_la_SOURCES_DIST = m17n-X.h m17n-X.c +@WITH_GUI_TRUE@am_libm17n_X_la_OBJECTS = m17n-X.lo +libm17n_X_la_OBJECTS = $(am_libm17n_X_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libm17n_X_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libm17n_X_la_LDFLAGS) $(LDFLAGS) -o $@ +@WITH_GUI_TRUE@am_libm17n_X_la_rpath = -rpath $(moduledir) +libm17n_core_la_DEPENDENCIES = +am_libm17n_core_la_OBJECTS = character.lo chartab.lo database.lo \ + plist.lo m17n-core.lo mtext.lo symbol.lo textprop.lo \ + mtext-lbrk.lo mtext-wseg.lo +libm17n_core_la_OBJECTS = $(am_libm17n_core_la_OBJECTS) +libm17n_core_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libm17n_core_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +@WITH_GUI_FALSE@am_libm17n_core_la_rpath = -rpath $(libdir) +@WITH_GUI_TRUE@am_libm17n_core_la_rpath = -rpath $(libdir) +libm17n_flt_la_DEPENDENCIES = ${top_builddir}/src/libm17n-core.la +am__objects_1 = m17n-flt.lo +am_libm17n_flt_la_OBJECTS = $(am__objects_1) +libm17n_flt_la_OBJECTS = $(am_libm17n_flt_la_OBJECTS) +libm17n_flt_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libm17n_flt_la_LDFLAGS) $(LDFLAGS) -o \ + $@ +@WITH_GUI_FALSE@am_libm17n_flt_la_rpath = -rpath $(libdir) +@WITH_GUI_TRUE@am_libm17n_flt_la_rpath = -rpath $(libdir) +@WITH_GUI_TRUE@libm17n_gd_la_DEPENDENCIES = \ +@WITH_GUI_TRUE@ ${top_builddir}/src/libm17n-core.la \ +@WITH_GUI_TRUE@ ${top_builddir}/src/libm17n.la \ +@WITH_GUI_TRUE@ ${top_builddir}/src/libm17n-flt.la \ +@WITH_GUI_TRUE@ ${top_builddir}/src/libm17n-gui.la +am__libm17n_gd_la_SOURCES_DIST = m17n-gd.c +@WITH_GUI_TRUE@am_libm17n_gd_la_OBJECTS = m17n-gd.lo +libm17n_gd_la_OBJECTS = $(am_libm17n_gd_la_OBJECTS) +libm17n_gd_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libm17n_gd_la_LDFLAGS) $(LDFLAGS) -o $@ +@WITH_GUI_TRUE@am_libm17n_gd_la_rpath = -rpath $(moduledir) +libm17n_gui_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + ${top_builddir}/src/libm17n-core.la \ + ${top_builddir}/src/libm17n.la \ + ${top_builddir}/src/libm17n-flt.la +am__objects_2 = face.lo font.lo font-ft.lo fontset.lo draw.lo \ + input-gui.lo m17n-gui.lo +am_libm17n_gui_la_OBJECTS = $(am__objects_2) +libm17n_gui_la_OBJECTS = $(am_libm17n_gui_la_OBJECTS) +libm17n_gui_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libm17n_gui_la_LDFLAGS) $(LDFLAGS) -o \ + $@ +@WITH_GUI_TRUE@am_libm17n_gui_la_rpath = -rpath $(libdir) +libm17n_la_DEPENDENCIES = ${top_builddir}/src/libm17n-core.la +am_libm17n_la_OBJECTS = charset.lo coding.lo input.lo language.lo \ + locale.lo m17n.lo +libm17n_la_OBJECTS = $(am_libm17n_la_OBJECTS) +libm17n_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libm17n_la_LDFLAGS) $(LDFLAGS) -o $@ +@WITH_GUI_FALSE@am_libm17n_la_rpath = -rpath $(libdir) +@WITH_GUI_TRUE@am_libm17n_la_rpath = -rpath $(libdir) +PROGRAMS = $(noinst_PROGRAMS) +am__linkcore_SOURCES_DIST = linkcore.c +@MAINTAINER_MODE_TRUE@am_linkcore_OBJECTS = linkcore.$(OBJEXT) +linkcore_OBJECTS = $(am_linkcore_OBJECTS) +@MAINTAINER_MODE_TRUE@linkcore_DEPENDENCIES = \ +@MAINTAINER_MODE_TRUE@ ${top_builddir}/src/libm17n-core.la +linkcore_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(linkcore_LDFLAGS) $(LDFLAGS) -o $@ +am__linkgui_SOURCES_DIST = linkgui.c +@MAINTAINER_MODE_TRUE@am_linkgui_OBJECTS = linkgui.$(OBJEXT) +linkgui_OBJECTS = $(am_linkgui_OBJECTS) +@MAINTAINER_MODE_TRUE@linkgui_DEPENDENCIES = \ +@MAINTAINER_MODE_TRUE@ ${top_builddir}/src/libm17n-gui.la +linkgui_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(linkgui_LDFLAGS) $(LDFLAGS) -o $@ +am__linkshell_SOURCES_DIST = linkshell.c +@MAINTAINER_MODE_TRUE@am_linkshell_OBJECTS = linkshell.$(OBJEXT) +linkshell_OBJECTS = $(am_linkshell_OBJECTS) +@MAINTAINER_MODE_TRUE@linkshell_DEPENDENCIES = \ +@MAINTAINER_MODE_TRUE@ ${top_builddir}/src/libm17n.la +linkshell_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(linkshell_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libm17n_X_la_SOURCES) $(libm17n_core_la_SOURCES) \ + $(libm17n_flt_la_SOURCES) $(libm17n_gd_la_SOURCES) \ + $(libm17n_gui_la_SOURCES) $(libm17n_la_SOURCES) \ + $(linkcore_SOURCES) $(linkgui_SOURCES) $(linkshell_SOURCES) +DIST_SOURCES = $(am__libm17n_X_la_SOURCES_DIST) \ + $(libm17n_core_la_SOURCES) $(libm17n_flt_la_SOURCES) \ + $(am__libm17n_gd_la_SOURCES_DIST) $(libm17n_gui_la_SOURCES) \ + $(libm17n_la_SOURCES) $(am__linkcore_SOURCES_DIST) \ + $(am__linkgui_SOURCES_DIST) $(am__linkshell_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__include_HEADERS_DIST = m17n-core.h m17n.h m17n-misc.h m17n-flt.h \ + m17n-gui.h m17n-X.h +HEADERS = $(include_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ + ChangeLog README +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +ANTHY_CFLAGS = @ANTHY_CFLAGS@ +ANTHY_LD_FLAGS = @ANTHY_LD_FLAGS@ +ANTHY_LIBS = @ANTHY_LIBS@ +API_VERSION = @API_VERSION@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_VISIBILITY = @CFLAG_VISIBILITY@ +CONFIG_FLAGS = @CONFIG_FLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FONTCONFIG_LD_FLAGS = @FONTCONFIG_LD_FLAGS@ +FREETYPE_LD_FLAGS = @FREETYPE_LD_FLAGS@ +FRIBIDI_LD_FLAGS = @FRIBIDI_LD_FLAGS@ +GD_LD_FLAGS = @GD_LD_FLAGS@ +GENCAT = @GENCAT@ +GETTEXTDIR = @GETTEXTDIR@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GLIBC2 = @GLIBC2@ +GLIBC21 = @GLIBC21@ +GLIB_2_0_CFLAGS = @GLIB_2_0_CFLAGS@ +GLIB_2_0_LIBS = @GLIB_2_0_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +HAVE_ASPRINTF = @HAVE_ASPRINTF@ +HAVE_FREETYPE_CONFIG = @HAVE_FREETYPE_CONFIG@ +HAVE_FRIBIDI_CONFIG = @HAVE_FRIBIDI_CONFIG@ +HAVE_ISPELL = @HAVE_ISPELL@ +HAVE_M17N_DB = @HAVE_M17N_DB@ +HAVE_OTFLIB_CONFIG = @HAVE_OTFLIB_CONFIG@ +HAVE_PKG_CONFIG = @HAVE_PKG_CONFIG@ +HAVE_POSIX_PRINTF = @HAVE_POSIX_PRINTF@ +HAVE_SNPRINTF = @HAVE_SNPRINTF@ +HAVE_VISIBILITY = @HAVE_VISIBILITY@ +HAVE_WPRINTF = @HAVE_WPRINTF@ +HAVE_XFT_CONFIG = @HAVE_XFT_CONFIG@ +HAVE_XML2_CONFIG = @HAVE_XML2_CONFIG@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLBISON = @INTLBISON@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBPTH = @LIBPTH@ +LIBPTH_PREFIX = @LIBPTH_PREFIX@ +LIBS = @LIBS@ +LIBTHAI_CFLAGS = @LIBTHAI_CFLAGS@ +LIBTHAI_LIBS = @LIBTHAI_LIBS@ +LIBTHREAD = @LIBTHREAD@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBC = @LTLIBC@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBPTH = @LTLIBPTH@ +LTLIBTHREAD = @LTLIBTHREAD@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +M17NDIR = @M17NDIR@ +M17N_MODULE_DIR = @M17N_MODULE_DIR@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTF_LD_FLAGS = @OTF_LD_FLAGS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSUB = @POSUB@ +POW_LIB = @POW_LIB@ +PRI_MACROS_BROKEN = @PRI_MACROS_BROKEN@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +THAI_WORDSEG_LD_FLAGS = @THAI_WORDSEG_LD_FLAGS@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WINDRES = @WINDRES@ +WOE32 = @WOE32@ +WOE32DLL = @WOE32DLL@ +WORDCUT_CFLAGS = @WORDCUT_CFLAGS@ +WORDCUT_LIBS = @WORDCUT_LIBS@ +X11_LD_FLAGS = @X11_LD_FLAGS@ +XAW_LD_FLAGS = @XAW_LD_FLAGS@ +XFT2_LD_FLAGS = @XFT2_LD_FLAGS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +XMKMF = @XMKMF@ +XML2_LD_FLAGS = @XML2_LD_FLAGS@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +VINFO = -version-info @API_VERSION@ +BASICBUILDS = libm17n-core.la libm17n.la libm17n-flt.la +@WITH_GUI_FALSE@BUILD_LIBS = $(BASICBUILDS) +@WITH_GUI_TRUE@BUILD_LIBS = $(BASICBUILDS) libm17n-gui.la +lib_LTLIBRARIES = $(BUILD_LIBS) +libm17n_core_la_SOURCES = \ + character.h character.c \ + chartab.h chartab.c \ + database.h database.c \ + internal.h \ + plist.h plist.c \ + m17n-core.h m17n-core.c \ + m17n-misc.h \ + mtext.h mtext.c \ + symbol.h symbol.c \ + textprop.h textprop.c \ + mtext-lbrk.c mtext-wseg.c + +libm17n_core_la_LIBADD = @XML2_LD_FLAGS@ @THAI_WORDSEG_LD_FLAGS@ +libm17n_core_la_LDFLAGS = -export-dynamic ${VINFO} +libm17n_la_SOURCES = \ + charset.h charset.c \ + coding.h coding.c \ + input.h input.c \ + language.h language.c \ + mlocale.h locale.c \ + m17n.h m17n.c + +libm17n_la_LIBADD = ${top_builddir}/src/libm17n-core.la -ldl +libm17n_la_LDFLAGS = -export-dynamic ${VINFO} +FLT_SOURCES = \ + internal-flt.h \ + m17n-flt.h m17n-flt.c + +libm17n_flt_la_SOURCES = ${FLT_SOURCES} +libm17n_flt_la_LIBADD = ${top_builddir}/src/libm17n-core.la +libm17n_flt_la_LDFLAGS = -export-dynamic ${VINFO} +GUI_SOURCES = \ + face.h face.c \ + font.h font.c font-ft.c \ + fontset.h fontset.c \ + draw.c \ + input-gui.c \ + internal-gui.h \ + m17n-gui.h m17n-gui.c + +OPTIONAL_LD_FLAGS = \ + @FREETYPE_LD_FLAGS@ \ + @FRIBIDI_LD_FLAGS@ \ + @OTF_LD_FLAGS@ \ + @FONTCONFIG_LD_FLAGS@ + +libm17n_gui_la_SOURCES = ${GUI_SOURCES} +libm17n_gui_la_LIBADD = ${OPTIONAL_LD_FLAGS} ${top_builddir}/src/libm17n-core.la ${top_builddir}/src/libm17n.la ${top_builddir}/src/libm17n-flt.la +libm17n_gui_la_LDFLAGS = -export-dynamic ${VINFO} +@WITH_GUI_TRUE@moduledir = ${libdir}/@M17N_MODULE_DIR@ +@WITH_GUI_TRUE@module_LTLIBRARIES = libm17n-X.la libm17n-gd.la +@WITH_GUI_TRUE@X_LD_FLAGS = ${X_PRE_LIBS} ${X_LIBS} @X11_LD_FLAGS@ ${X_EXTRA_LIBS} +@WITH_GUI_TRUE@libm17n_X_la_SOURCES = m17n-X.h m17n-X.c +@WITH_GUI_TRUE@libm17n_X_la_LIBADD = ${X_LD_FLAGS} @XFT2_LD_FLAGS@ @FONTCONFIG_LD_FLAGS@ ${top_builddir}/src/libm17n-core.la ${top_builddir}/src/libm17n.la ${top_builddir}/src/libm17n-flt.la ${top_builddir}/src/libm17n-gui.la +@WITH_GUI_TRUE@libm17n_X_la_LDFLAGS = -avoid-version -module +@WITH_GUI_TRUE@libm17n_gd_la_SOURCES = m17n-gd.c +@WITH_GUI_TRUE@libm17n_gd_la_LIBADD = @GD_LD_FLAGS@ @FREETYPE_LD_FLAGS@ ${top_builddir}/src/libm17n-core.la ${top_builddir}/src/libm17n.la ${top_builddir}/src/libm17n-flt.la ${top_builddir}/src/libm17n-gui.la +@WITH_GUI_TRUE@libm17n_gd_la_LDFLAGS = -avoid-version -module +AM_CPPFLAGS = -DM17NDIR=\"@M17NDIR@\" -DM17N_MODULE_DIR=\"${libdir}/@M17N_MODULE_DIR@\" -DGETTEXTDIR=\"@GETTEXTDIR@\" +BASICHEADERS = m17n-core.h m17n.h m17n-misc.h m17n-flt.h +@WITH_GUI_FALSE@include_HEADERS = $(BASICHEADERS) +@WITH_GUI_TRUE@include_HEADERS = $(BASICHEADERS) m17n-gui.h m17n-X.h +SRC = ${libm17n_core_la_SOURCES} \ + ${libm17n_la_SOURCES} \ + ${libm17n_gui_la_SOURCES} \ + ${libm17n_X_la_SOURCES} \ + ${libm17n_gd_la_SOURCES} + +@MAINTAINER_MODE_TRUE@linkcore_SOURCES = linkcore.c +@MAINTAINER_MODE_TRUE@linkcore_LDADD = ${top_builddir}/src/libm17n-core.la +@MAINTAINER_MODE_TRUE@linkcore_LDFLAGS = -static +@MAINTAINER_MODE_TRUE@linkshell_SOURCES = linkshell.c +@MAINTAINER_MODE_TRUE@linkshell_LDADD = ${top_builddir}/src/libm17n.la +@MAINTAINER_MODE_TRUE@linkshell_LDFLAGS = -static +@MAINTAINER_MODE_TRUE@linkgui_SOURCES = linkgui.c +@MAINTAINER_MODE_TRUE@linkgui_LDADD = ${top_builddir}/src/libm17n-gui.la +@MAINTAINER_MODE_TRUE@linkgui_LDFLAGS = -static +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +install-moduleLTLIBRARIES: $(module_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(module_LTLIBRARIES)'; test -n "$(moduledir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(moduledir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(moduledir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(moduledir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(moduledir)"; \ + } + +uninstall-moduleLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(module_LTLIBRARIES)'; test -n "$(moduledir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(moduledir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(moduledir)/$$f"; \ + done + +clean-moduleLTLIBRARIES: + -test -z "$(module_LTLIBRARIES)" || rm -f $(module_LTLIBRARIES) + @list='$(module_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libm17n-X.la: $(libm17n_X_la_OBJECTS) $(libm17n_X_la_DEPENDENCIES) $(EXTRA_libm17n_X_la_DEPENDENCIES) + $(AM_V_CCLD)$(libm17n_X_la_LINK) $(am_libm17n_X_la_rpath) $(libm17n_X_la_OBJECTS) $(libm17n_X_la_LIBADD) $(LIBS) + +libm17n-core.la: $(libm17n_core_la_OBJECTS) $(libm17n_core_la_DEPENDENCIES) $(EXTRA_libm17n_core_la_DEPENDENCIES) + $(AM_V_CCLD)$(libm17n_core_la_LINK) $(am_libm17n_core_la_rpath) $(libm17n_core_la_OBJECTS) $(libm17n_core_la_LIBADD) $(LIBS) + +libm17n-flt.la: $(libm17n_flt_la_OBJECTS) $(libm17n_flt_la_DEPENDENCIES) $(EXTRA_libm17n_flt_la_DEPENDENCIES) + $(AM_V_CCLD)$(libm17n_flt_la_LINK) $(am_libm17n_flt_la_rpath) $(libm17n_flt_la_OBJECTS) $(libm17n_flt_la_LIBADD) $(LIBS) + +libm17n-gd.la: $(libm17n_gd_la_OBJECTS) $(libm17n_gd_la_DEPENDENCIES) $(EXTRA_libm17n_gd_la_DEPENDENCIES) + $(AM_V_CCLD)$(libm17n_gd_la_LINK) $(am_libm17n_gd_la_rpath) $(libm17n_gd_la_OBJECTS) $(libm17n_gd_la_LIBADD) $(LIBS) + +libm17n-gui.la: $(libm17n_gui_la_OBJECTS) $(libm17n_gui_la_DEPENDENCIES) $(EXTRA_libm17n_gui_la_DEPENDENCIES) + $(AM_V_CCLD)$(libm17n_gui_la_LINK) $(am_libm17n_gui_la_rpath) $(libm17n_gui_la_OBJECTS) $(libm17n_gui_la_LIBADD) $(LIBS) + +libm17n.la: $(libm17n_la_OBJECTS) $(libm17n_la_DEPENDENCIES) $(EXTRA_libm17n_la_DEPENDENCIES) + $(AM_V_CCLD)$(libm17n_la_LINK) $(am_libm17n_la_rpath) $(libm17n_la_OBJECTS) $(libm17n_la_LIBADD) $(LIBS) + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +linkcore$(EXEEXT): $(linkcore_OBJECTS) $(linkcore_DEPENDENCIES) $(EXTRA_linkcore_DEPENDENCIES) + @rm -f linkcore$(EXEEXT) + $(AM_V_CCLD)$(linkcore_LINK) $(linkcore_OBJECTS) $(linkcore_LDADD) $(LIBS) + +linkgui$(EXEEXT): $(linkgui_OBJECTS) $(linkgui_DEPENDENCIES) $(EXTRA_linkgui_DEPENDENCIES) + @rm -f linkgui$(EXEEXT) + $(AM_V_CCLD)$(linkgui_LINK) $(linkgui_OBJECTS) $(linkgui_LDADD) $(LIBS) + +linkshell$(EXEEXT): $(linkshell_OBJECTS) $(linkshell_DEPENDENCIES) $(EXTRA_linkshell_DEPENDENCIES) + @rm -f linkshell$(EXEEXT) + $(AM_V_CCLD)$(linkshell_LINK) $(linkshell_OBJECTS) $(linkshell_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/character.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/charset.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chartab.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coding.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/database.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/draw.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/face.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/font-ft.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/font.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fontset.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/input-gui.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/input.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/language.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linkcore.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linkgui.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linkshell.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/locale.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m17n-X.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m17n-core.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m17n-flt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m17n-gd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m17n-gui.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m17n.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mtext-lbrk.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mtext-wseg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mtext.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plist.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symbol.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/textprop.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(moduledir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + clean-moduleLTLIBRARIES clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-includeHEADERS install-moduleLTLIBRARIES + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES \ + uninstall-moduleLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool clean-moduleLTLIBRARIES \ + clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-includeHEADERS install-info \ + install-info-am install-libLTLIBRARIES install-man \ + install-moduleLTLIBRARIES install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-includeHEADERS \ + uninstall-libLTLIBRARIES uninstall-moduleLTLIBRARIES + +.PRECIOUS: Makefile + + +TAGS: ${SRC} + etags ${SRC} + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/README b/src/README new file mode 100644 index 0000000..646e5b6 --- /dev/null +++ b/src/README @@ -0,0 +1,52 @@ +Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 +See the end for copying conditions. + +Naming convention. + +name-space internal external +========== ======== ======== +function mobject__xxx mobject_xxx +symbol variable Mobject__xxx Mobject_xxx +other variable mobject__xxx mobject_xxx +constant macro MOBJECT_XXX +other macro MOBJECT_XXX +type MObject[Xxx] + +A structure is named as MXxxxx and is `typedef'ed with the same name. +Ex: typedef struct MFace MFace + +In comments, a structure member is denoted simply as `', +but a member of a specific structure is denoted as +`MStruct->member_name'. If the member itself is a structure (or a +pointer to a structure) and has a sub-member, the sub-member is +denoted as: + `' + or `sub_name>' + or `MStruct->member_name.subname' + or `MStruct->member_name->subname' + +---------------------------------------------------------------------- +Copyright information + +Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + +This file is part of the m17n library. + +The m17n 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 m17n 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 m17n library; if not, write to the Free +Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. diff --git a/src/character.c b/src/character.c new file mode 100644 index 0000000..46745f2 --- /dev/null +++ b/src/character.c @@ -0,0 +1,659 @@ +/* character.c -- character module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nCharacter + @brief Character objects and API for them. + + The m17n library represents a @e character by a character code (an + integer). The minimum character code is @c 0. The maximum + character code is defined by the macro #MCHAR_MAX. It is + assured that #MCHAR_MAX is not smaller than @c 0x3FFFFF (22 + bits). + + Characters @c 0 to @c 0x10FFFF are equivalent to the Unicode + characters of the same code values. + + A character can have zero or more properties called @e character + @e properties. A character property consists of a @e key and a + @e value, where key is a symbol and value is anything that can be + cast to (void *). "The character property that belongs + to character C and whose key is K" may be shortened to "the K + property of C". */ + +/***ja + @addtogroup m17nCharacter + @brief ʸ�����֥������ȤȤ���˴ؤ��� API. + + m17n �饤�֥��� @e ʸ�� ��ʸ�������ɡ������ˤ�ɽ�����롣 + �Ǿ���ʸ�������ɤ� @c 0 �Ǥ��ꡢ�����ʸ�������ɤϥޥ��� #MCHAR_MAX + �ˤ�ä��������Ƥ��롣#MCHAR_MAX �� @c 0x3FFFFF��22�ӥåȡ� + �ʾ�Ǥ��뤳�Ȥ��ݾڤ���Ƥ��롣 + + @c 0 ���� @c 0x10FFFF �ޤǤ�ʸ���ϡ������Ʊ���ͤ���� Unicode + ��ʸ���˳�����Ƥ��Ƥ��롣 + + ��ʸ���� @e ʸ���ץ��ѥƥ� �ȸƤ֥ץ��ѥƥ��� 0 �İʾ���Ĥ��Ȥ��Ǥ��롣 + ʸ���ץ��ѥƥ��� @e ���� �� @e �� ����ʤ롣 + �����ϥ���ܥ�Ǥ��ꡢ�ͤ� (void *) ���˥��㥹�ȤǤ����Τʤ鲿�Ǥ�褤�� + ��ʸ�� C ��ʸ���ץ��ѥƥ��Τ��������� K �Ǥ����Ρפ��ñ�ˡ�ʸ�� C + �� K �ץ��ѥƥ��פȸƤ֤��Ȥ����롣 */ +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include +#include +#include +#include + +#include "m17n-core.h" +#include "m17n-misc.h" +#include "internal.h" + +typedef struct +{ + MSymbol type; + void *mdb; + MCharTable *table; +} MCharPropRecord; + +static MPlist *char_prop_list; + +static void +free_string (int from, int to, void *str, void *arg) +{ + free (str); +} + + +/* Internal API */ + +int +mchar__init () +{ + Mname = msymbol ("name"); + Mcategory = msymbol ("category"); + Mcombining_class = msymbol ("combining-class"); + Mbidi_category = msymbol ("bidirectional-category"); + Msimple_case_folding = msymbol ("simple-case-folding"); + Mcomplicated_case_folding = msymbol ("complicated-case-folding"); + Mcased = msymbol ("cased"); + Msoft_dotted = msymbol ("soft-dotted"); + Mcase_mapping = msymbol ("case-mapping"); + Mblock = msymbol ("block"); + Mscript = msymbol ("script"); + + return 0; +} + +void +mchar__fini (void) +{ + MPlist *p; + + if (char_prop_list) + { + for (p = char_prop_list; mplist_key (p) != Mnil; p = mplist_next (p)) + { + MCharPropRecord *record = mplist_value (p); + + if (record->table) + { + if (record->type == Mstring) + mchartable_map (record->table, NULL, free_string, NULL); + M17N_OBJECT_UNREF (record->table); + } + free (record); + } + M17N_OBJECT_UNREF (char_prop_list); + } +} + +void +mchar__define_prop (MSymbol key, MSymbol type, void *mdb) +{ + MCharPropRecord *record; + + if (char_prop_list) + record = mplist_get (char_prop_list, key); + else + char_prop_list = mplist (), record = NULL; + if (record) + { + if (record->table) + M17N_OBJECT_UNREF (record->table); + } + else + { + MSTRUCT_CALLOC (record, MERROR_CHAR); + mplist_put (char_prop_list, key, record); + } + + record->type = type; + record->mdb = mdb; + if (mdb) + { + record->table = NULL; + } + else + { + void *default_value = NULL; + + if (type == Minteger) + default_value = (void *) -1; + record->table = mchartable (type, default_value); + } +} + + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + +/* External API */ + +/*** @addtogroup m17nCharacter + @{ */ +/*=*/ + +#ifdef FOR_DOXYGEN +/***en + @brief Maximum character code. + + The macro #MCHAR_MAX gives the maximum character code. */ + +/***ja + @brief ʸ�������ɤκ�����. + + �ޥ��� #MCHAR_MAX ��ʸ�������ɤκ����ͤ�ɽ���� */ + +#define MCHAR_MAX +/*=*/ +#endif /* FOR_DOXYGEN */ + +/***en + @name Variables: Keys of character properties + + These symbols are used as keys of character properties. */ + +/***ja + @ingroup m17nCharacter + @name �ѿ�: ʸ���ץ��ѥƥ��Υ��� + + �����Υ���ܥ��ʸ���ץ��ѥƥ��Υ����Ȥ��ƻȤ��롣*/ + +/*=*/ +/*** @{ */ + +/***en + @brief Key for script. + + The symbol #Mscript has the name "script" and is used as the key + of a character property. The value of such a property is a symbol + representing the script to which the character belongs. + + Each symbol that represents a script has one of the names listed in + the Unicode Technical Report #24. */ + +/***ja + @brief ������ץȤ�ɽ�魯����. + + ����ܥ� #Mscript �� "script" + �Ȥ���̾���������ʸ���ץ��ѥƥ��Υ����Ȥ��ƻȤ��롣 + ���Υץ��ѥƥ����ͤϡ�����ʸ����°���륹����ץȤ�ɽ�魯����ܥ�Ǥ��롣 + + ������ץȤ�ɽ�魯����ܥ��̾���ϡ�Unicode Technical Report + #24 �˥ꥹ�Ȥ���Ƥ����ΤΤ����줫�Ǥ��롣 */ + +MSymbol Mscript; + +/*=*/ + +/***en + @brief Key for character name. + + The symbol #Mname has the name "name" and is used as + the key of a character property. The value of such a property is a + C-string representing the name of the character. */ + +/***ja + @brief ̾����ɽ�魯����. + + ����ܥ� #Mname �� "name" + �Ȥ���̾���������ʸ���ץ��ѥƥ��Υ����Ȥ��ƻȤ��롣 + ���Υץ��ѥƥ����ͤϤ���ʸ����̾����ɽ�魯 C ��ʸ����Ǥ��롣 */ + +MSymbol Mname; + +/*=*/ + +/***en + @brief Key for general category. + + The symbol #Mcategory has the name "category" and is + used as the key of a character property. The value of such a + property is a symbol representing the general category of + the character. + + Each symbol that represents a general category has one of the + names listed as abbreviations for General Category in + Unicode. */ + +/***ja + @brief ���̥��ƥ����ɽ�魯����. + + ����ܥ� #Mcategory �� "category" + �Ȥ���̾���������ʸ���ץ��ѥƥ��Υ����Ȥ��ƻȤ��롣 + ���Υץ��ѥƥ����ͤϡ��б����� ���̥��ƥ��� ��ɽ�魯����ܥ�Ǥ��롣 + + ���̥��ƥ����ɽ�魯����ܥ��̾���ϡ�General Category + �ξ�ά���Ȥ��� Unicode ���������Ƥ����ΤǤ��롣 */ + +MSymbol Mcategory; + +/*=*/ + +/***en + @brief Key for canonical combining class. + + The symbol #Mcombining_class has the name + "combining-class" and is used as the key of a character + property. The value of such a property is an integer that + represents the canonical combining class of the character. + + The meaning of each integer that represents a canonical combining + class is identical to the one defined in Unicode. */ + +/***ja + @brief ɸ���祯�饹��ɽ�魯����. + + ����ܥ� #Mcombining_class �� "combining-class" + �Ȥ���̾���������ʸ���ץ��ѥƥ��Υ����Ȥ��ƻȤ��롣 + ���Υץ��ѥƥ����ͤϡ��б����� @e ɸ���祯�饹 ��ɽ�魯�����Ǥ��롣 + + ɸ���祯�饹��ɽ�魯�����ΰ�̣�ϡ�Unicode + ���������Ƥ����Τ�Ʊ���Ǥ��롣 */ + +MSymbol Mcombining_class; +/*=*/ + +/***en + @brief Key for bidi category. + + The symbol #Mbidi_category has the name "bidi-category" + and is used as the key of a character property. The value of such + a property is a symbol that represents the bidirectional + category of the character. + + Each symbol that represents a bidirectional category has one of + the names listed as types of Bidirectional Category in + Unicode. */ + +/***ja + @brief ���������ƥ����ɽ�魯����. + + ����ܥ� #Mbidi_category �� "bidi-category" + �Ȥ���̾���������ʸ���ץ��ѥƥ��Υ����Ȥ��ƻȤ��롣 + ���Υץ��ѥƥ����ͤϡ��б����� @e ���������ƥ��� ��ɽ�魯����ܥ�Ǥ��롣 + + ���������ƥ����ɽ�魯����ܥ��̾���ϡ�Bidirectional + Category �η��Ȥ��� Unicode ���������Ƥ����ΤǤ��롣 */ + +MSymbol Mbidi_category; +/*=*/ + +/***en + @brief Key for corresponding single lowercase character. + + The symbol #Msimple_case_folding has the name + "simple-case-folding" and is used as the key of a + character property. The value of such a property is the + corresponding single lowercase character that is used when + comparing M-texts ignoring cases. + + If a character requires a complicated comparison (i.e. cannot be + compared by simply mapping to another single character), the value + of such a property is @c 0xFFFF. In this case, the character has + another property whose key is #Mcomplicated_case_folding. */ + +/***ja + @brief �б����뾮ʸ����ʸ����ɽ�魯����. + + ����ܥ� #Msimple_case_folding �� "simple-case-folding" + �Ȥ���̾���������ʸ���ץ��ѥƥ��Υ����Ȥ��ƻȤ��롣 + ���Υץ��ѥƥ����ͤϡ��б����뾮ʸ����ʸ���Ǥ��ꡢ��ʸ������ʸ���ζ��̤�̵�뤷��ʸ������Ӥκݤ˻Ȥ��롣 + + ʣ���������ˡ��ɬ�פȤ���ʸ���Ǥ��ä���� + ���̤ΰ�ʸ�����б��դ��뤳�Ȥˤ�ä���ӤǤ��ʤ����ˡ����Υץ��ѥƥ����ͤ� + @c 0xFFFF �ˤʤ롣���ξ�礽��ʸ���ϡ�#Mcomplicated_case_folding + �Ȥ���������ʸ���ץ��ѥƥ�����ġ� */ + +MSymbol Msimple_case_folding; +/*=*/ + +/***en + @brief Key for corresponding multiple lowercase characters. + + The symbol #Mcomplicated_case_folding has the name + "complicated-case-folding" and is used as the key of a + character property. The value of such a property is the + corresponding M-text that contains a sequence of lowercase + characters to be used for comparing M-texts ignoring case. */ + +/***ja + @brief �б����뾮ʸ�������ɽ�魯����. + + ����ܥ� #Mcomplicated_case_folding �� + "complicated-case-folding" + �Ȥ���̾���������ʸ���ץ��ѥƥ��Υ����Ȥ��ƻȤ��롣 + ���Υץ��ѥƥ����ͤϡ��б����뾮ʸ���󤫤�ʤ� M-text �Ǥ��ꡢ��ʸ������ʸ���ζ��̤�̵�뤷��ʸ������Ӥκݤ˻� + ���롣 + */ + +MSymbol Mcomplicated_case_folding; +/*=*/ + +/***en + @brief Key for values used in case operation. + + The symbol #Mcased has the name "cased" and is used as + the key of charater property. The value of such a property is an + integer value 1, 2, or 3 representing "cased", "case-ignorable", + and both of them respective. See the Unicode Standard 5.0 + (Section 3.13 Default Case Algorithm) for the detail. + */ + +/***ja + @brief Case �������Ѥ������ͤΥ���. + + ����ܥ� #Mcased �ϡ�"cased" �Ȥ���̾���������ʸ���ץ��� + �ƥ��Υ����Ȥ��ƻȤ��롣���Υץ��ѥƥ����ͤ������� 1, 2, 3 �Τ��� + �줫�Ǥ��ꡢ���줾�� "cased", "case-ignorable", ����ξ�����̣���롣 + �ܺ٤ˤĤ��Ƥϡ�the Unicode Standard 5.0 (Section 3.13 Default + Case Algorithm) ���ȡ� + */ +MSymbol Mcased; + +/*=*/ +/***en + @brief Key for values used in case operation. + + The symbol #Msoft_dotted has the name "soft-dotted" and + is used as the key of charater property. The value of such a + property is #Mt if a character has "Soft_Dotted" property, and + #Mnil otherwise. See the Unicode Standard 5.0 (Section 3.13 + Default Case Algorithm) for the detail. */ + +/***ja + @brief Case �������Ѥ������ͤΥ���. + + ����ܥ� #Msoft_dotted �ϡ�"soft-dotted" �Ȥ���̾��������� + ʸ���ץ��ѥƥ��Υ����Ȥ��ƻȤ��롣���Υץ��ѥƥ����ͤϡ�ʸ���� + "Soft_Dotted"�ץ��ѥƥ�����ľ��ˤ� #Mt, �����Ǥʤ���� #Mnil �� + ���롣 �ܺ٤ˤĤ��Ƥϡ�the Unicode Standard 5.0 (Section 3.13 + Default Case Algorithm) ���ȡ� + */ +MSymbol Msoft_dotted; + +/*=*/ +/***en + @brief Key for values used in case operation. + + The symbol #Mcase_mapping has the name "case-mapping" and + is used as the key of charater property. The value of such a + property is a plist of three M-Texts; lower, title, and upper of + the corresponding character. See the Unicode Standard 5.0 + (Section 5.18 Case Mappings) for the detail. */ + +/***ja + @brief Case �������Ѥ������ͤΥ���. + + ����ܥ� #Mcase_mapping �ϡ�"case-mapping" �Ȥ���̾����� + ����ʸ���ץ��ѥƥ��Υ����Ȥ��ƻȤ��롣���Υץ��ѥƥ����ͤϡ����� + �� M-text�����ʤ������ʸ���� lower, title, �� upper����ʤ� plist + �Ǥ��롣 �ܺ٤ˤĤ��Ƥϡ�the Unicode Standard 5.0 (Section 3.13 + Default Case Algorithm) ���ȡ� +*/ +MSymbol Mcase_mapping; + +/*=*/ +/***en + @brief Key for script block name. + + The symbol #Mblock the name "block" and is used as the + key of charater property. The value of such a property is a + symbol representing a script block of the corresponding + character. */ +/***ja + @brief ������ץȥ֥��å�̾��ɽ������. + + ����ܥ� #Mblock �ϡ�"block" �Ȥ���̾��������ʸ���ץ��� + �ƥ��Υ����Ȥ��ƻȤ��롣���Υץ��ѥƥ����ͤϡ�����ʸ���Υ������ + �ȥ֥��å�̾��ɽ������ܥ�Ǥ��롣*/ +MSymbol Mblock; + +/*** @} */ +/*=*/ + +/***en + @brief Define a character property. + + The mchar_define_property () function searches the m17n database + for a data whose tags are \<#Mchar_table, $TYPE, $SYM \>. + Here, $SYM is a symbol whose name is $NAME. $TYPE must be + #Mstring, #Mtext, #Msymbol, #Minteger, or #Mplist. + + @return + If the operation was successful, mchar_define_property () returns + $SYM. Otherwise it returns #Mnil. */ + +/***ja + @brief ʸ���ץ��ѥƥ����������. + + �ؿ� mchar_define_property () �ϡ� \<#Mchar_table, $TYPE, $SYM \> + �Ȥ�����������ä��ǡ����١����� m17n �������١�������õ���� + ������ $SYM �� $NAME �Ȥ���̾���Υ���ܥ�Ǥ��롣$TYPE ��#Mstring, + #Mtext, #Msymbol, #Minteger, #Mplist �Τ����줫�Ǥʤ���Фʤ�ʤ��� + + @return + ��������������� mchar_define_property () ��$SYM ���֤��� + ���Ԥ������� #Mnil ���֤��� */ + +/*** + @errors + @c MERROR_DB + + @seealso + mchar_get_prop (), mchar_put_prop () */ + +MSymbol +mchar_define_property (const char *name, MSymbol type) +{ + MSymbol key = msymbol (name); + void *mdb; + + mdb = mdatabase_find (Mchar_table, type, key, Mnil); + if (! mdb) + return Mnil; + mchar__define_prop (key, type, mdb); + return key; +} + +/*=*/ + +/***en + @brief Get the value of a character property. + + The mchar_get_prop () function searches character $C for the + character property whose key is $KEY. + + @return + If the operation was successful, mchar_get_prop () returns the + value of the character property. Otherwise it returns @c + NULL. */ + +/***ja + @brief ʸ���ץ��ѥƥ����ͤ�����. + + �ؿ� mchar_get_prop () �ϡ�ʸ�� $C ��ʸ���ץ��ѥƥ��Τ��������� + $KEY �Ǥ����Τ�õ���� + + @return + ��������������� mchar_get_prop () �ϸ��Ĥ��ä��ץ��ѥƥ����ͤ��֤��� + ���Ԥ������� @c NULL ���֤��� + + @latexonly \IPAlabel{mchar_get_prop} @endlatexonly +*/ +/*** + @errors + @c MERROR_SYMBOL, @c MERROR_DB + + @seealso + mchar_define_property (), mchar_put_prop () */ + +void * +mchar_get_prop (int c, MSymbol key) +{ + MCharPropRecord *record; + + if (! char_prop_list) + return NULL; + record = mplist_get (char_prop_list, key); + if (! record) + return NULL; + if (record->mdb) + { + record->table = mdatabase_load (record->mdb); + if (! record->table) + MERROR (MERROR_DB, NULL); + record->mdb = NULL; + } + return mchartable_lookup (record->table, c); +} + +/*=*/ + +/***en + @brief Set the value of a character property. + + The mchar_put_prop () function searches character $C for the + character property whose key is $KEY and assigns $VAL to the value + of the found property. + + @return + If the operation was successful, mchar_put_prop () returns 0. + Otherwise, it returns -1. */ +/***ja + @brief ʸ���ץ��ѥƥ����ͤ����ꤹ��. + + �ؿ� mchar_put_prop () �ϡ�ʸ�� $C ��ʸ���ץ��ѥƥ��Τ��������� $KEY + �Ǥ����Τ�õ���������ͤȤ��� $VAL �����ꤹ�롣 + + @return + ��������������� mchar_put_prop () ��0���֤������Ԥ�������-1���֤��� */ +/*** + @errors + @c MERROR_SYMBOL, @c MERROR_DB + + @seealso + mchar_define_property (), mchar_get_prop () */ + +int +mchar_put_prop (int c, MSymbol key, void *val) +{ + MCharPropRecord *record; + + if (! char_prop_list) + MERROR (MERROR_CHAR, -1); + record = mplist_get (char_prop_list, key); + if (! record) + return -1; + if (record->mdb) + { + record->table = mdatabase_load (record->mdb); + if (! record->table) + MERROR (MERROR_DB, -1); + record->mdb = NULL; + } + return mchartable_set (record->table, c, val); +} + +/*=*/ + +/***en + @brief Get the char-table for a character property. + + The mchar_get_prop_table () function returns a char-table that + contains the character property whose key is $KEY. If $TYPE is + not NULL, this function stores the type of the property in the + place pointed by $TYPE. See mchar_define_property () for types of + character property. + + @return + If $KEY is a valid character property key, this function returns a + char-table. Otherwise NULL is retuned. */ + +/***ja + @brief ʸ���ץ��ѥƥ���ʸ���ơ��֥������. + + �ؿ� mchar_get_prop_table () �ϡ������� $KEY �Ǥ���ʸ���ץ��ѥƥ� + ��ޤ�ʸ���ơ��֥���֤����⤷ $TYPE �� NULL �Ǥʤ���С� $TYPE �� + �ؤ������ˤ���ʸ���Υץ��ѥƥ����Ǽ���롣ʸ���ץ��ѥƥ��μ��� + �˴ؤ��Ƥ� mchar_define_property () �򸫤衣 + + @return + �⤷ $KEY ��������ʸ���ץ��ѥƥ��Υ����Ǥ���С�ʸ���ơ��֥뤬�֤� + ��롣�����Ǥʤ����� NULL ���֤���롣 */ + +MCharTable * +mchar_get_prop_table (MSymbol key, MSymbol *type) +{ + MCharPropRecord *record; + + if (! char_prop_list) + return NULL; + record = mplist_get (char_prop_list, key); + if (! record) + return NULL; + if (record->mdb) + { + record->table = mdatabase_load (record->mdb); + if (! record->table) + MERROR (MERROR_DB, NULL); + record->mdb = NULL; + } + if (type) + *type = record->type; + return record->table; +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/character.h b/src/character.h new file mode 100644 index 0000000..2b4e1f4 --- /dev/null +++ b/src/character.h @@ -0,0 +1,290 @@ +/* character.h -- header file for the character module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_CHARACTER_H_ +#define _M17N_CHARACTER_H_ + +/* UTF-8 format + + 0-7F 0xxxxxxx + 80-7FF 110xxxxx 10xxxxxx + 800-FFFF 1110xxxx 10xxxxxx 10xxxxxx + 10000-1FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + 200000-3FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + 4000000-7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + + Unicode range: + 0-10FFFF 0 - 11110uuu 10uuxxxx 10xxxxxx 10xxxxxx (uuuuu <= 0x10) + +*/ + +#define MAX_UTF8_CHAR_BYTES 6 +#define MAX_UNICODE_CHAR_BYTES 4 + +#define USHORT_SIZE (sizeof (unsigned short)) +#define UINT_SIZE (sizeof (unsigned int)) + +/* Return how many bytes one unit (char, short, or int) in FORMAT + occupies. */ + +#define UNIT_BYTES(format) \ + ((format) <= MTEXT_FORMAT_UTF_8 ? 1 \ + : (format) <= MTEXT_FORMAT_UTF_16BE ? USHORT_SIZE \ + : UINT_SIZE) + +/* Return how many units (char, short, or int) C will occupy in + MText->data. If C is not in the supported range, return 0. */ + +#define CHAR_UNITS_ASCII(c) ((c) < 0x80) + +#define CHAR_UNITS_UTF8(c) \ + ((c) < 0x80 ? 1 \ + : (c) < 0x800 ? 2 \ + : (c) < 0x10000 ? 3 \ + : (c) < 0x200000 ? 4 \ + : (c) < 0x4000000 ? 5 \ + : 6) + +#define CHAR_UNITS_UTF16(c) ((c) < 0x110000 ? (2 - ((c) < 0x10000)) : 0) + +#define CHAR_UNITS_UTF32(c) 1 + +#define CHAR_UNITS(c, format) \ + ((format) <= MTEXT_FORMAT_UTF_8 ? CHAR_UNITS_UTF8 (c) \ + : (format) <= MTEXT_FORMAT_UTF_16BE ? CHAR_UNITS_UTF16 (c) \ + : CHAR_UNITS_UTF32 (c)) + +#define CHAR_BYTES CHAR_UNITS_UTF8 + +#define CHAR_UNITS_AT_UTF8(p) \ + (!(*(p) & 0x80) ? 1 \ + : !(*(p) & 0x20) ? 2 \ + : !(*(p) & 0x10) ? 3 \ + : !(*(p) & 0x08) ? 4 \ + : !(*(p) & 0x04) ? 5 \ + : !(*(p) & 0x02) ? 6 \ + : 0) + +#define CHAR_UNITS_AT_UTF16(p) \ + (2 - (*(unsigned short *) (p) < 0xD800 \ + || *(unsigned short *) (p) >= 0xDC00)) + +#define CHAR_UNITS_AT(mt, p) \ + ((mt)->format <= MTEXT_FORMAT_UTF_8 ? CHAR_UNITS_AT_UTF8 (p) \ + : (mt)->format <= MTEXT_FORMAT_UTF_16BE ? CHAR_UNITS_AT_UTF16 (p) \ + : 1) + +#define CHAR_BYTES_AT CHAR_UNITS_AT_UTF8 + +#define CHAR_UNITS_BY_HEAD_UTF8(c) \ + (!((c) & 0x80) ? 1 \ + : !((c) & 0x20) ? 2 \ + : !((c) & 0x10) ? 3 \ + : !((c) & 0x08) ? 4 \ + : !((c) & 0x04) ? 5 \ + : !((c) & 0x02) ? 6 \ + : 0) + +#define CHAR_UNITS_BY_HEAD_UTF16(c) \ + (2 - ((unsigned short) (c) < 0xD800 || (unsigned short) (c) >= 0xDC00)) + +#define CHAR_UNITS_BY_HEAD(c, format) \ + ((format) <= MTEXT_FORMAT_UTF_8 ? CHAR_UNITS_BY_HEAD_UTF8 (c) \ + : (format) <= MTEXT_FORMAT_UTF_16BE ? CHAR_UNITS_BY_HEAD_UTF16 (c) \ + : 1) + +#define CHAR_BYTES_BY_HEAD CHAR_UNITS_BY_HEAD_UTF8 + +#define STRING_CHAR_UTF8(p) \ + (!((p)[0] & 0x80) ? (p)[0] \ + : !((p)[0] & 0x20) ? ((((p)[0] & 0x1F) << 6) \ + | ((p)[1] & 0x3F)) \ + : !((p)[0] & 0x10) ? ((((p)[0] & 0x0F) << 12) \ + | (((p)[1] & 0x3F) << 6) \ + | ((p)[2] & 0x3F)) \ + : !((p)[0] & 0x08) ? ((((p)[0] & 0x07) << 18) \ + | (((p)[1] & 0x3F) << 12) \ + | (((p)[2] & 0x3F) << 6) \ + | ((p)[3] & 0x3F)) \ + : !((p)[0] & 0x04) ? ((((p)[0] & 0x03) << 24) \ + | (((p)[1] & 0x3F) << 18) \ + | (((p)[2] & 0x3F) << 12) \ + | (((p)[3] & 0x3F) << 6) \ + | ((p)[4] & 0x3F)) \ + : ((((p)[0] & 0x01) << 30) \ + | (((p)[1] & 0x3F) << 24) \ + | (((p)[2] & 0x3F) << 18) \ + | (((p)[3] & 0x3F) << 12) \ + | (((p)[4] & 0x3F) << 6) \ + | ((p)[5] & 0x3F))) + +#define STRING_CHAR_UTF16(p) \ + (((unsigned short) (p)[0] < 0xD800 || (unsigned short) (p)[0] >= 0xDC00) \ + ? (p)[0] \ + : ((((p)[0] - 0xD800) << 10) + ((p)[1] - 0xDC00) + 0x10000)) + + +#define STRING_CHAR STRING_CHAR_UTF8 + + +#define STRING_CHAR_ADVANCE_UTF8(p) \ + (!(*(p) & 0x80) ? ((p)++, (p)[-1]) \ + : !(*(p) & 0x20) ? ((p) += 2, ((((p)[-2] & 0x1F) << 6) \ + | ((p)[-1] & 0x3F))) \ + : !(*(p) & 0x10) ? ((p) += 3, ((((p)[-3] & 0x0F) << 12) \ + | (((p)[-2] & 0x3F) << 6) \ + | ((p)[-1] & 0x3F))) \ + : !(*(p) & 0x08) ? ((p) += 4, ((((p)[-4] & 0x07) << 18) \ + | (((p)[-3] & 0x3F) << 12) \ + | (((p)[-2] & 0x3F) << 6) \ + | ((p)[-1] & 0x3F))) \ + : !(*(p) & 0x04) ? ((p) += 5, ((((p)[-5] & 0x03) << 24) \ + | (((p)[-4] & 0x3F) << 18) \ + | (((p)[-3] & 0x3F) << 12) \ + | (((p)[-2] & 0x3F) << 6) \ + | ((p)[-1] & 0x3F))) \ + : ((p) += 6, ((((p)[-6] & 0x01) << 30) \ + | (((p)[-5] & 0x3F) << 24) \ + | (((p)[-4] & 0x3F) << 18) \ + | (((p)[-3] & 0x3F) << 12) \ + | (((p)[-2] & 0x3F) << 6) \ + | ((p)[-1] & 0x3F)))) + +#define STRING_CHAR_ADVANCE_UTF16(p) \ + (((p)[0] < 0xD800 || (p)[0] >= 0xDC00) \ + ? ((p)++, (p)[-1]) \ + : ((p) += 2, ((((p)[-2] - 0xD800) << 10) + ((p)[-1] - 0xDC00) + 0x10000))) + +#define STRING_CHAR_ADVANCE STRING_CHAR_ADVANCE_UTF8 + +#define STRING_CHAR_AND_UNITS_UTF8(p, bytes) \ + (!((p)[0] & 0x80) ? ((bytes) = 1, (p)[0]) \ + : !((p)[0] & 0x20) ? ((bytes) = 2, \ + ((((p)[0] & 0x1F) << 6) \ + | ((p)[1] & 0x3F))) \ + : !((p)[0] & 0x10) ? ((bytes) = 3, \ + ((((p)[0] & 0x0F) << 12) \ + | (((p)[1] & 0x3F) << 6) \ + | ((p)[2] & 0x3F))) \ + : !((p)[0] & 0x08) ? ((bytes) = 4, \ + ((((p)[0] & 0x07) << 18) \ + | (((p)[1] & 0x3F) << 12) \ + | (((p)[2] & 0x3F) << 6) \ + | ((p)[3] & 0x3F))) \ + : !((p)[0] & 0x04) ? ((bytes) = 5, \ + ((((p)[0] & 0x03) << 24) \ + | (((p)[1] & 0x3F) << 18) \ + | (((p)[2] & 0x3F) << 12) \ + | (((p)[3] & 0x3F) << 6) \ + | ((p)[4] & 0x3F))) \ + : ((bytes) = 6, \ + ((((p)[0] & 0x01) << 30) \ + | (((p)[1] & 0x3F) << 24) \ + | (((p)[2] & 0x3F) << 18) \ + | (((p)[3] & 0x3F) << 12) \ + | (((p)[4] & 0x3F) << 6) \ + | ((p)[5] & 0x3F)))) + +#define STRING_CHAR_AND_UNITS_UTF16(p, units) \ + (((unsigned short) (p)[0] < 0xD800 || (unsigned short) (p)[0] >= 0xDC00) \ + ? ((units) = 1, (p)[0]) \ + : ((units) = 2, \ + (((p)[0] - 0xD800) << 10) + ((p)[1] - 0xDC00) + 0x10000)) + +#define STRING_CHAR_AND_UNITS(p, units, format) \ + ((format) <= MTEXT_FORMAT_UTF_8 \ + ? STRING_CHAR_AND_UNITS_UTF8 (p, units) \ + : (format) <= MTEXT_FORMAT_UTF_16BE \ + ? STRING_CHAR_AND_UNITS_UTF16 (p, units) \ + : ((units) = 1, ((unsigned) (p))[0])) + + +#define STRING_CHAR_AND_BYTES STRING_CHAR_AND_UNITS_UTF8 + +#define CHAR_STRING_UTF8(c, p) \ + ((c) < 0x80 \ + ? ((p)[0] = (c), 1) \ + : (c) < 0x800 ? ((p)[0] = (0xC0 | ((c) >> 6)), \ + (p)[1] = (0x80 | ((c) & 0x3F)), \ + 2) \ + : (c) < 0x10000 ? ((p)[0] = (0xE0 | ((c) >> 12)), \ + (p)[1] = (0x80 | (((c) >> 6) & 0x3F)), \ + (p)[2] = (0x80 | ((c) & 0x3F)), \ + 3) \ + : (c) < 0x200000 ? ((p)[0] = (0xF0 | ((c) >> 18)), \ + (p)[1] = (0x80 | (((c) >> 12) & 0x3F)), \ + (p)[2] = (0x80 | (((c) >> 6) & 0x3F)), \ + (p)[3] = (0x80 | ((c) & 0x3F)), \ + 4) \ + : (c) < 0x4000000 ? ((p)[0] = 0xF8, \ + (p)[1] = (0x80 | ((c) >> 18)), \ + (p)[2] = (0x80 | (((c) >> 12) & 0x3F)), \ + (p)[3] = (0x80 | (((c) >> 6) & 0x3F)), \ + (p)[4] = (0x80 | ((c) & 0x3F)), \ + 5) \ + : ((p)[0] = (0xFC | ((c) >> 30)), \ + (p)[1] = (0x80 | (((c) >> 24) & 0x3F)), \ + (p)[2] = (0x80 | (((c) >> 18) & 0x3F)), \ + (p)[3] = (0x80 | (((c) >> 12) & 0x3F)), \ + (p)[4] = (0x80 | (((c) >> 6) & 0x3F)), \ + (p)[5] = (0x80 | ((c) & 0x3F)), \ + 6)) + +#define CHAR_STRING_UTF16(c, p) \ + ((c) < 0x10000 ? (p)[0] = (c), 1 \ + : (p[0] = (((c) - 0x10000) >> 10) + 0xD800, \ + p[1] = (((c) - 0x10000) & 0x3FF) + 0xDC00, \ + 2)) + +#define CHAR_STRING CHAR_STRING_UTF8 + +#define CHAR_HEAD_P_UTF8(p) \ + ((*(p) & 0xC0) != 0x80) + +#define CHAR_HEAD_P_UTF16(p) \ + (*(unsigned short *) (p) < 0xDC00 \ + || *(unsigned short *) (p) >= 0xE000) + +#define CHAR_HEAD_P CHAR_HEAD_P_UTF8 + +/** Locale-safe version of tolower (). It works only for an ASCII + character. */ +#define TOLOWER(c) (((c) >= 'A' && (c) <= 'Z') ? (c) + 32 : (c)) + +/** Locale-safe version of toupper (). It works only for an ASCII + character. */ +#define TOUPPER(c) (((c) >= 'a' && (c) <= 'z') ? (c) - 32 : (c)) + +/** Locale-safe version of isupper (). It works only for an ASCII + character. */ +#define ISUPPER(c) ((c) >= 'A' && (c) <= 'Z') + +/** Locale-safe version of isalnum (). It works only for an ASCII + character. */ +#define ISALNUM(c) \ + (((c) >= 'A' && (c) <= 'Z') \ + || ((c) >= 'a' && (c) <= 'z') \ + || ((c) >= '0' && (c) <= '9')) + +extern void mchar__define_prop (MSymbol key, MSymbol type, void *mdb); + +#endif /* not _M17N_CHARACTER_H_ */ diff --git a/src/charset.c b/src/charset.c new file mode 100644 index 0000000..efeb8ad --- /dev/null +++ b/src/charset.c @@ -0,0 +1,1549 @@ +/* charset.c -- charset module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ +/***en + @addtogroup m17nCharset + @brief Charset objects and API for them. + + The m17n library uses @e charset objects to represent a coded + character sets (CCS). The m17n library supports many predefined + coded character sets. Moreover, application programs can add + other charsets. A character can belong to multiple charsets. + + The m17n library distinguishes the following three concepts: + + @li A @e code-point is a number assigned by the CCS to each + character. Code-points may or may not be continuous. The type + @c unsigned is used to represent a code-point. An invalid + code-point is represented by the macro @c MCHAR_INVALID_CODE. + + @li A @e character @e index is the canonical index of a character + in a CCS. The character that has the character index N occupies + the Nth position when all the characters in the current CCS are + sorted by their code-points. Character indices in a CCS are + continuous and start with 0. + + @li A @e character @e code is the internal representation in the + m17n library of a character. A character code is a signed integer + of 21 bits or longer. + + Each charset object defines how characters are converted between + code-points and character codes. To @e encode means converting + code-points to character codes and to @e decode means converting + character codes to code-points. */ + +/***ja + @addtogroup m17nCharset + @brief ʸ�����åȥ��֥������ȤȤ���˴ؤ��� API. + + m17n �饤�֥��ϡ���沽ʸ������ (CCS) �� @e ʸ�����å� + �ȸƤ֥��֥������Ȥ�ɽ�����롣 + m17n �饤�֥���¿������沽ʸ������򤢤餫���᥵�ݡ��Ȥ��Ƥ��뤷�����ץꥱ�������ץ�����ब�ȼ���ʸ�����åȤ��ɲä��뤳�Ȥ��ǽ�Ǥ��롣 + ��Ĥ�ʸ����ʣ����ʸ�����åȤ�°���Ƥ�褤�� + + m17n �饤�֥��ϡ��ʲ��γ�ǰ����̤��Ƥ���: + + @li @e �����ɥݥ���� �Ȥϡ�CCS ��������θġ���ʸ�����Ф������������ͤǤ��롣 + �����ɥݥ���Ȥ�Ϣ³���Ƥ���Ȥϸ¤�ʤ��������ɥݥ���Ȥ� + @c unsigned ���ˤ�ä�ɽ����롣̵���ʥ����ɥݥ���Ȥϥޥ��� + @c MCHAR_INVALID_CODE ��ɽ����롣 + + @li @e ʸ������ǥå��� �Ȥϡ�CCS ��dz�ʸ���˳�����Ƥ������������줿����ǥå����Ǥ��롣 + ʸ������ǥå����� N ��ʸ���ϡ�CCS �����ʸ���򥳡��ɥݥ���Ƚ���¤٤��Ȥ��� N ���ܤ˸����롣 + CCS ���ʸ������ǥå�����Ϣ³���Ƥ��ꡢ0 ����Ϥޤ롣 + + @li @e ʸ�������� �Ȥϡ�m17n �饤�֥����ˤ�����ʸ��������ɽ���Ǥ��ꡢ21 �ӥåȰʾ��Ĺ�����������դ������Ǥ��롣 + + ��ʸ�����åȥ��֥������Ȥϡ�����ʸ�����åȤ�°����ʸ���Υ����ɥݥ���Ȥ�ʸ�������ɤȤδ֤��Ѵ����ꤹ�롣 + �����ɥݥ���Ȥ���ʸ�������ɤؤ��Ѵ��� @e �ǥ����� + �ȸƤӡ�ʸ�������ɤ��饳���ɥݥ���Ȥؤ��Ѵ��� @e ���󥳡��� �ȸƤ֡� */ + + +/*=*/ +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include +#include +#include + +#include "m17n.h" +#include "m17n-misc.h" +#include "internal.h" +#include "symbol.h" +#include "database.h" +#include "chartab.h" +#include "plist.h" +#include "charset.h" +#include "coding.h" + +static int unified_max; + +/** List of all charsets ever defined. */ + +struct MCharsetList +{ + int size, inc, used; + MCharset **charsets; +}; + +static struct MCharsetList charset_list; + +static MPlist *charset_definition_list; + +/** Make a charset object from the template of MCharset structure + CHARSET, and return a pointer to the new charset object. + CHARSET->code_range[4N + 2] and CHARSET->code_range[4N + 3] are + not yet set. */ + +static MCharset * +make_charset (MCharset *charset) +{ + unsigned min_code, max_code; + int i, n; + int *range = charset->code_range; + + if (charset->dimension < 1 || charset->dimension > 4) + MERROR (MERROR_CHARSET, NULL); + if ((charset->final_byte > 0 && charset->final_byte < '0') + || charset->final_byte > 127) + MERROR (MERROR_CHARSET, NULL); + + for (i = 0, n = 1; i < 4; i++) + { + if (range[i * 4] > range[i * 4 + 1]) + MERROR (MERROR_CHARSET, NULL); + range[i * 4 + 2] = range[i * 4 + 1] - range[i * 4] + 1; + n *= range[i * 4 + 2]; + range[i * 4 + 3] = n; + } + + min_code = range[0] | (range[4] << 8) | (range[8] << 16) | (range[12] << 24); + if (charset->min_code == 0) + charset->min_code = min_code; + else if (charset->min_code < min_code) + MERROR (MERROR_CHARSET, NULL); + max_code = range[1] | (range[5] << 8) | (range[9] << 16) | (range[13] << 24); + if (charset->max_code == 0) + charset->max_code = max_code; + else if (charset->max_code > max_code) + MERROR (MERROR_CHARSET, NULL); + + charset->code_range_min_code = min_code; + charset->fully_loaded = 0; + charset->simple = 0; + + if (charset->method == Msubset) + { + MCharset *parent; + + if (charset->nparents != 1) + MERROR (MERROR_CHARSET, NULL); + parent = charset->parents[0]; + if (parent->method == Msuperset + || charset->min_code - charset->subset_offset < parent->min_code + || charset->max_code - charset->subset_offset > parent->max_code) + MERROR (MERROR_CHARSET, NULL); + } + else if (charset->method == Msuperset) + { + if (charset->nparents < 2) + MERROR (MERROR_CHARSET, NULL); + for (i = 0; i < charset->nparents; i++) + if (charset->min_code > charset->parents[i]->min_code + || charset->max_code < charset->parents[i]->max_code) + MERROR (MERROR_CHARSET, NULL); + } + else + { + charset->no_code_gap + = (charset->dimension == 1 + || (range[2] == 256 + && (charset->dimension == 2 + || (range[6] == 256 + && (charset->dimension == 3 + || range[10] == 256))))); + + if (! charset->no_code_gap) + { + int j; + + memset (charset->code_range_mask, 0, + sizeof charset->code_range_mask); + for (i = 0; i < 4; i++) + for (j = range[i * 4]; j <= range[i * 4 + 1]; j++) + charset->code_range_mask[j] |= (1 << i); + } + + if (charset->method == Moffset) + { + charset->max_char = charset->min_char + range[15] - 1; + if (charset->min_char < 0 + || charset->max_char < 0 || charset->max_char > unified_max) + MERROR (MERROR_CHARSET, NULL); + charset->simple = charset->no_code_gap; + charset->fully_loaded = 1; + } + else if (charset->method == Munify) + { + /* The magic number 12 below is to align to the SUB_BITS_2 + (defined in chartab.c) boundary in a char-table. */ + unified_max -= ((range[15] >> 12) + 1) << 12; + charset->unified_max = unified_max; + } + else if (charset->method != Mmap) + MERROR (MERROR_CHARSET, NULL); + } + + MLIST_APPEND1 (&charset_list, charsets, charset, MERROR_CHARSET); + + if (charset->final_byte > 0) + { + MLIST_APPEND1 (&mcharset__iso_2022_table, charsets, charset, + MERROR_CHARSET); + if (charset->revision <= 0) + { + int chars = range[2]; + + if (chars == 128) /* ASCII case */ + chars = 94; + else if (chars == 256) /* ISO-8859-X case */ + chars = 96; + MCHARSET_ISO_2022 (charset->dimension, chars, charset->final_byte) + = charset; + } + } + + return charset; +} + +static int +load_charset_fully (MCharset *charset) +{ + if (charset->method == Msubset) + { + MCharset *parent = charset->parents[0]; + + if (! parent->fully_loaded + && load_charset_fully (parent) < 0) + MERROR (MERROR_CHARSET, -1); + if (parent->method == Moffset) + { + unsigned code; + + code = charset->min_code - charset->subset_offset; + charset->min_char = DECODE_CHAR (parent, code); + code = charset->max_code - charset->subset_offset; + charset->max_char = DECODE_CHAR (parent, code); + } + else + { + unsigned min_code = charset->min_code - charset->subset_offset; + unsigned max_code = charset->max_code - charset->subset_offset; + int min_char = DECODE_CHAR (parent, min_code); + int max_char = min_char; + + for (++min_code; min_code <= max_code; min_code++) + { + int c = DECODE_CHAR (parent, min_code); + + if (c >= 0) + { + if (c < min_char) + min_char = c; + else if (c > max_char) + max_char = c; + } + } + charset->min_char = min_char; + charset->max_char = max_char; + } + } + else if (charset->method == Msuperset) + { + int min_char = 0, max_char = 0; + int i; + + for (i = 0; i < charset->nparents; i++) + { + MCharset *parent = charset->parents[i]; + + if (! parent->fully_loaded + && load_charset_fully (parent) < 0) + MERROR (MERROR_CHARSET, -1); + if (i == 0) + min_char = parent->min_char, max_char = parent->max_char; + else if (parent->min_char < min_char) + min_char = parent->min_char; + else if (parent->max_char > max_char) + max_char = parent->max_char; + } + charset->min_char = min_char; + charset->max_char = max_char; + } + else /* charset->method is Mmap or Munify */ + { + MDatabase *mdb = mdatabase_find (Mcharset, charset->name, Mnil, Mnil); + MPlist *plist; + + if (! mdb || ! (plist = mdatabase_load (mdb))) + MERROR (MERROR_CHARSET, -1); + charset->decoder = mplist_value (plist); + charset->encoder = mplist_value (mplist_next (plist)); + M17N_OBJECT_UNREF (plist); + mchartable_range (charset->encoder, + &charset->min_char, &charset->max_char); + if (charset->method == Mmap) + charset->simple = charset->no_code_gap; + else + charset->max_char = charset->unified_max + 1 + charset->code_range[15]; + } + + charset->fully_loaded = 1; + return 0; +} + +/** Load a data of type @c charset from the file FD. */ + +static void * +load_charset (FILE *fp, MSymbol charset_name) +{ + MCharset *charset = MCHARSET (charset_name); + int *decoder; + MCharTable *encoder; + int size; + int i, c; + int found = 0; + MPlist *plist; + + if (! charset) + MERROR (MERROR_DB, NULL); + size = (charset->code_range[15] + - (charset->min_code - charset->code_range_min_code)); + MTABLE_MALLOC (decoder, size, MERROR_DB); + for (i = 0; i < size; i++) + decoder[i] = -1; + encoder = mchartable (Minteger, (void *) MCHAR_INVALID_CODE); + + while ((c = getc (fp)) != EOF) + { + unsigned code1, code2, c1, c2; + int idx1, idx2; + char buf[256]; + + ungetc (c, fp); + if (! fgets (buf, 256, fp)) + break; + if (c != '#') + { + if (sscanf (buf, "0x%x-0x%x 0x%x", &code1, &code2, &c1) == 3) + { + idx1 = CODE_POINT_TO_INDEX (charset, code1); + if (idx1 >= size) + continue; + idx2 = CODE_POINT_TO_INDEX (charset, code2); + if (idx2 >= size) + idx2 = size - 1; + c2 = c1 + (idx2 - idx1); + } + else if (sscanf (buf, "0x%x 0x%x", &code1, &c1) == 2) + { + idx1 = idx2 = CODE_POINT_TO_INDEX (charset, code1); + if (idx1 >= size) + continue; + c2 = c1; + } + else + continue; + if (idx1 >= 0 && idx2 >= 0) + { + decoder[idx1] = c1; + mchartable_set (encoder, c1, (void *) code1); + for (idx1++, c1++; idx1 <= idx2; idx1++, c1++) + { + code1 = INDEX_TO_CODE_POINT (charset, idx1); + decoder[idx1] = c1; + mchartable_set (encoder, c1, (void *) code1); + } + found++; + } + } + } + + if (! found) + { + free (decoder); + M17N_OBJECT_UNREF (encoder); + return NULL; + } + plist = mplist (); + mplist_add (plist, Mt, decoder); + mplist_add (plist, Mt, encoder); + return plist; +} + + +/* Internal API */ + +MPlist *mcharset__cache; + +/* Predefined charsets. */ +MCharset *mcharset__ascii; +MCharset *mcharset__binary; +MCharset *mcharset__m17n; +MCharset *mcharset__unicode; + +MCharsetISO2022Table mcharset__iso_2022_table; + +/** Initialize charset handler. */ + +int +mcharset__init () +{ + MPlist *param, *pl; + + unified_max = MCHAR_MAX; + + mdatabase__load_charset_func = load_charset; + mcharset__cache = mplist (); + mplist_set (mcharset__cache, Mt, NULL); + + MLIST_INIT1 (&charset_list, charsets, 128); + MLIST_INIT1 (&mcharset__iso_2022_table, charsets, 128); + charset_definition_list = mplist (); + + memset (mcharset__iso_2022_table.classified, 0, + sizeof (mcharset__iso_2022_table.classified)); + + Mmethod = msymbol ("method"); + Moffset = msymbol ("offset"); + Mmap = msymbol ("map"); + Munify = msymbol ("unify"); + Msubset = msymbol ("subset"); + Msuperset = msymbol ("superset"); + + Mdimension = msymbol ("dimension"); + Mmin_range = msymbol ("min-range"); + Mmax_range = msymbol ("max-range"); + Mmin_code = msymbol ("min-code"); + Mmax_code = msymbol ("max-code"); + Mascii_compatible = msymbol ("ascii-compatible"); + Mfinal_byte = msymbol ("final-byte"); + Mrevision = msymbol ("revision"); + Mmin_char = msymbol ("min-char"); + Mmapfile = msymbol_as_managing_key ("mapfile"); + Mparents = msymbol_as_managing_key ("parents"); + Msubset_offset = msymbol ("subset-offset"); + Mdefine_coding = msymbol ("define-coding"); + Maliases = msymbol_as_managing_key ("aliases"); + + param = mplist (); + pl = param; + /* Setup predefined charsets. */ + pl = mplist_add (pl, Mmethod, Moffset); + pl = mplist_add (pl, Mmin_range, (void *) 0); + pl = mplist_add (pl, Mmax_range, (void *) 0x7F); + pl = mplist_add (pl, Mascii_compatible, Mt); + pl = mplist_add (pl, Mfinal_byte, (void *) 'B'); + pl = mplist_add (pl, Mmin_char, (void *) 0); + Mcharset_ascii = mchar_define_charset ("ascii", param); + + mplist_put (param, Mmax_range, (void *) 0xFF); + mplist_put (param, Mfinal_byte, NULL); + Mcharset_iso_8859_1 = mchar_define_charset ("iso-8859-1", param); + + mplist_put (param, Mmax_range, (void *) 0x10FFFF); + Mcharset_unicode = mchar_define_charset ("unicode", param); + + mplist_put (param, Mmax_range, (void *) MCHAR_MAX); + Mcharset_m17n = mchar_define_charset ("m17n", param); + + mplist_put (param, Mmax_range, (void *) 0xFF); + Mcharset_binary = mchar_define_charset ("binary", param); + + M17N_OBJECT_UNREF (param); + + mcharset__ascii = MCHARSET (Mcharset_ascii); + mcharset__binary = MCHARSET (Mcharset_binary); + mcharset__m17n = MCHARSET (Mcharset_m17n); + mcharset__unicode = MCHARSET (Mcharset_unicode); + + return 0; +} + +void +mcharset__fini (void) +{ + int i; + MPlist *plist; + + for (i = 0; i < charset_list.used; i++) + { + MCharset *charset = charset_list.charsets[i]; + + if (charset->decoder) + free (charset->decoder); + if (charset->encoder) + M17N_OBJECT_UNREF (charset->encoder); + free (charset); + } + M17N_OBJECT_UNREF (mcharset__cache); + MLIST_FREE1 (&charset_list, charsets); + MLIST_FREE1 (&mcharset__iso_2022_table, charsets); + MPLIST_DO (plist, charset_definition_list) + M17N_OBJECT_UNREF (MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (charset_definition_list); +} + + +MCharset * +mcharset__find (MSymbol name) +{ + MCharset *charset; + + charset = msymbol_get (name, Mcharset); + if (! charset) + { + MPlist *param = mplist_get (charset_definition_list, name); + + MPLIST_KEY (mcharset__cache) = Mt; + if (! param) + return NULL; + param = mplist__from_plist (param); + mchar_define_charset (MSYMBOL_NAME (name), param); + charset = msymbol_get (name, Mcharset); + M17N_OBJECT_UNREF (param); + } + MPLIST_KEY (mcharset__cache) = name; + MPLIST_VAL (mcharset__cache) = charset; + return charset; +} + + +/** Return the character corresponding to code-point CODE in CHARSET. + If CODE is invalid for CHARSET, return -1. */ + +int +mcharset__decode_char (MCharset *charset, unsigned code) +{ + int idx; + + if (code < 128 && charset->ascii_compatible) + return (int) code; + if (code < charset->min_code || code > charset->max_code) + return -1; + + if (! charset->fully_loaded + && load_charset_fully (charset) < 0) + MERROR (MERROR_CHARSET, -1); + + if (charset->method == Msubset) + { + MCharset *parent = charset->parents[0]; + + code -= charset->subset_offset; + return DECODE_CHAR (parent, code); + } + + if (charset->method == Msuperset) + { + int i; + + for (i = 0; i < charset->nparents; i++) + { + MCharset *parent = charset->parents[i]; + int c = DECODE_CHAR (parent, code); + + if (c >= 0) + return c; + } + return -1; + } + + idx = CODE_POINT_TO_INDEX (charset, code); + if (idx < 0) + return -1; + + if (charset->method == Mmap) + return charset->decoder[idx]; + + if (charset->method == Munify) + { + int c = charset->decoder[idx]; + + if (c < 0) + c = charset->unified_max + 1 + idx; + return c; + } + + /* Now charset->method should be Moffset. */ + return (charset->min_char + idx); +} + + +/** Return the code point of character C in CHARSET. If CHARSET does not + contain C, return MCHAR_INVALID_CODE. */ + +unsigned +mcharset__encode_char (MCharset *charset, int c) +{ + if (! charset->fully_loaded + && load_charset_fully (charset) < 0) + MERROR (MERROR_CHARSET, MCHAR_INVALID_CODE); + + if (charset->method == Msubset) + { + MCharset *parent = charset->parents[0]; + unsigned code = ENCODE_CHAR (parent, c); + + if (code == MCHAR_INVALID_CODE) + return code; + code += charset->subset_offset; + if (code >= charset->min_code && code <= charset->max_code) + return code; + return MCHAR_INVALID_CODE; + } + + if (charset->method == Msuperset) + { + int i; + + for (i = 0; i < charset->nparents; i++) + { + MCharset *parent = charset->parents[i]; + unsigned code = ENCODE_CHAR (parent, c); + + if (code != MCHAR_INVALID_CODE) + return code; + } + return MCHAR_INVALID_CODE; + } + + if (c < charset->min_char || c > charset->max_char) + return MCHAR_INVALID_CODE; + + if (charset->method == Mmap) + return (unsigned) mchartable_lookup (charset->encoder, c); + + if (charset->method == Munify) + { + if (c > charset->unified_max) + { + c -= charset->unified_max - 1; + return INDEX_TO_CODE_POINT (charset, c); + } + return (unsigned) mchartable_lookup (charset->encoder, c); + } + + /* Now charset->method should be Moffset */ + c -= charset->min_char; + return INDEX_TO_CODE_POINT (charset, c); +} + +int +mcharset__load_from_database () +{ + MDatabase *mdb = mdatabase_find (msymbol ("charset-list"), Mnil, Mnil, Mnil); + MPlist *def_list, *plist; + MPlist *definitions = charset_definition_list; + int mdebug_flag = MDEBUG_CHARSET; + + if (! mdb) + return 0; + MDEBUG_PUSH_TIME (); + def_list = (MPlist *) mdatabase_load (mdb); + MDEBUG_PRINT_TIME ("CHARSET", (mdebug__output, " to load data.")); + MDEBUG_POP_TIME (); + if (! def_list) + return -1; + + MDEBUG_PUSH_TIME (); + MPLIST_DO (plist, def_list) + { + MPlist *pl, *p; + MSymbol name; + + if (! MPLIST_PLIST_P (plist)) + MERROR (MERROR_CHARSET, -1); + pl = MPLIST_PLIST (plist); + if (! MPLIST_SYMBOL_P (pl)) + MERROR (MERROR_CHARSET, -1); + name = MPLIST_SYMBOL (pl); + pl = MPLIST_NEXT (pl); + definitions = mplist_add (definitions, name, pl); + M17N_OBJECT_REF (pl); + p = mplist__from_plist (pl); + mchar_define_charset (MSYMBOL_NAME (name), p); + M17N_OBJECT_UNREF (p); + } + + M17N_OBJECT_UNREF (def_list); + MDEBUG_PRINT_TIME ("CHARSET", (mdebug__output, " to parse the loaded data.")); + MDEBUG_POP_TIME (); + return 0; +} + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/* External API */ + +/*** @addtogroup m17nCharset */ +/*** @{ */ +/*=*/ + +#ifdef FOR_DOXYGEN +/***en + @brief Invalid code-point. + + The macro #MCHAR_INVALID_CODE gives the invalid code-point. */ + +/***ja + @brief ̵���ʥ����ɥݥ����. + + �ޥ��� #MCHAR_INVALID_CODE ��̵���ʥ����ɥݥ���Ȥ򼨤��� */ + +#define MCHAR_INVALID_CODE +#endif + +/*=*/ + +/***en + @name Variables: Symbols representing a charset. + + Each of the following symbols represents a predefined charset. */ + +/***ja + @name �ѿ�: ʸ�����åȤ�ɽ����������Ѥߥ���ܥ�. + + �ʲ��γƥ���ܥ�ϡ�����Ѥ�ʸ�����åȤ�ɽ�����롣 */ +/*=*/ +/*** @{ */ +/*=*/ +/***en + @brief Symbol representing the charset ASCII. + + The symbol #Mcharset_ascii has name "ascii" and represents + the charset ISO 646, USA Version X3.4-1968 (ISO-IR-6). */ +/***ja + @brief ASCII ʸ�����åȤ�ɽ�����륷��ܥ�. + + ����ܥ� #Mcharset_ascii �� "ascii" �Ȥ���̾��������� + ISO 646, USA Version X3.4-1968 (ISO-IR-6) ʸ�����åȤ�ɽ�����롣 + */ + +MSymbol Mcharset_ascii; + +/*=*/ +/***en + @brief Symbol representing the charset ISO/IEC 8859/1. + + The symbol #Mcharset_iso_8859_1 has name "iso-8859-1" + and represents the charset ISO/IEC 8859-1:1998. */ +/***ja + @brief ISO/IEC 8859-1:1998 ʸ�����åȤ�ɽ�����륷��ܥ�. + + ����ܥ� #Mcharset_iso_8859_1 �� "iso-8859-1" + �Ȥ���̾���������ISO/IEC 8859-1:1998 ʸ�����åȤ�ɽ�����롣 + */ + +MSymbol Mcharset_iso_8859_1; + +/***en + @brief Symbol representing the charset Unicode. + + The symbol #Mcharset_unicode has name "unicode" and + represents the charset Unicode. */ +/***ja + @brief Unicode ʸ�����åȤ�ɽ�����륷��ܥ�. + + ����ܥ� #Mcharset_unicode �� "unicode" + �Ȥ���̾���������Unicode ʸ�����åȤ�ɽ�����롣 */ + +MSymbol Mcharset_unicode; + +/*=*/ +/***en + @brief Symbol representing the largest charset. + + The symbol #Mcharset_m17n has name "m17n" and + represents the charset that contains all characters supported by + the m17n library. */ +/***ja + @brief ��ʸ����ޤ�ʸ�����åȤ�ɽ�����륷��ܥ�. + + ����ܥ� #Mcharset_m17n �� "m17n" �Ȥ���̾��������� + m17n �饤�֥�꤬�������Ƥ�ʸ����ޤ�ʸ�����åȤ�ɽ�����롣 */ + +MSymbol Mcharset_m17n; + +/*=*/ +/***en + @brief Symbol representing the charset for ill-decoded characters. + + The symbol #Mcharset_binary has name "binary" and + represents the fake charset which the decoding functions put to an + M-text as a text property when they encounter an invalid byte + (sequence). + + See @ref m17nConv for more details. */ + +/***ja + @brief �������ǥ����ɤǤ��ʤ�ʸ����ʸ�����åȤ�ɽ�����륷��ܥ�. + + ����ܥ� #Mcharset_binary �� "binary" + �Ȥ���̾������������� (fake) ʸ�����åȤ�ɽ�����롣 + �ǥ����ɴؿ��ϡ�M-text �Υƥ����ȥץ��ѥƥ��Ȥ��ơ�̵���ʥХ��ȡʥ��������󥹡ˤ������������֤��ղä��롣 + + �ܺ٤� @ref m17nConv ���ȤΤ��ȡ� */ + +MSymbol Mcharset_binary; + +/*=*/ +/*** @} */ +/*=*/ + +/***en + @name Variables: Parameter keys for mchar_define_charset (). + + These are the predefined symbols to use as parameter keys for the + function mchar_define_charset () (which see). */ + +/***ja + @name �ѿ�: mchar_define_charset �ѤΥѥ�᡼�������� + + �����ϡ��ؿ� mchar_define_charset () �ѤΥѥ�᡼���������Ȥ��ƻȤ��륷��ܥ�Ǥ��롣 + �ܤ����Ϥ��δؿ��β���򻲾ȤΤ��ȡ�*/ +/*** @{ */ +/*=*/ + +MSymbol Mmethod; +MSymbol Mdimension; +MSymbol Mmin_range; +MSymbol Mmax_range; +MSymbol Mmin_code; +MSymbol Mmax_code; +MSymbol Mascii_compatible; +MSymbol Mfinal_byte; +MSymbol Mrevision; +MSymbol Mmin_char; +MSymbol Mmapfile; +MSymbol Mparents; +MSymbol Msubset_offset; +MSymbol Mdefine_coding; +MSymbol Maliases; +/*=*/ +/*** @} */ +/*=*/ + +/***en + @name Variables: Symbols representing charset methods. + + These are the predefined symbols that can be a value of the + @b Mmethod parameter of a charset used in an argument to the + mchar_define_charset () function. + + A method specifies how code-points and character codes are + converted. See the documentation of the mchar_define_charset () + function for the details. */ + +/***ja + @name �ѿ�: ʸ�����åȤΥ᥽�åɻ���˻Ȥ��륷��ܥ� + + �����ϡ�ʸ�����åȤ� @e �᥽�å� ����ꤹ�뤿�������Ѥߥ���ܥ�Ǥ��ꡢʸ�����åȤ� + @b Mmethod �ѥ�᡼�����ͤȤʤ뤳�Ȥ��Ǥ��롣 + �����ͤϴؿ� mchar_define_charset () �ΰ����Ȥ��ƻȤ��롣 + + �᥽�åɤȤϡ������ɥݥ���Ȥ�ʸ�������ɤ�����Ѵ�����ݤ������Τ��ȤǤ��롣 + �ܤ����ϴؿ� mchar_define_charset () �β���򻲾ȤΤ��ȡ� */ +/*** @{ */ +/*=*/ +/***en + @brief Symbol for the offset type method of charset. + + The symbol #Moffset has the name "offset" and, when used + as a value of @b Mmethod parameter of a charset, it means that the + conversion of code-points and character codes of the charset is + done by this calculation: + +@verbatim +CHARACTER-CODE = CODE-POINT - MIN-CODE + MIN-CHAR +@endverbatim + + where, MIN-CODE is a value of @b Mmin_code parameter of the charset, + and MIN-CHAR is a value of @b Mmin_char parameter. */ + +/***ja + @brief ���ե��åȷ��Υ᥽�åɤ򼨤�����ܥ�. + + ����ܥ� #Moffset �� "offset" �Ȥ���̾���������ʸ�����åȤ� + @b Mmethod �ѥ�᡼�����ͤȤ����Ѥ���줿���ˤϡ������ɥݥ���Ȥ�ʸ�����åȤ�ʸ�������ɤδ֤��Ѵ����ʲ��μ��˽��äƹԤ��뤳�Ȥ��̣���롣 + +@verbatim +ʸ�������� = �����ɥݥ���� - MIN-CODE + MIN-CHAR +@endverbatim + + �����ǡ�MIN-CODE ��ʸ�����åȤ� @b Mmin_code �ѥ�᡼�����ͤǤ��ꡢMIN-CHAR �� + @b Mmin_char �ѥ�᡼�����ͤǤ��롣 */ + +MSymbol Moffset; +/*=*/ + +/***en @brief Symbol for the map type method of charset. + + The symbol #Mmap has the name "map" and, when used as a + value of @b Mmethod parameter of a charset, it means that the + conversion of code-points and character codes of the charset is + done by map looking up. The map must be given by @b Mmapfile + parameter. */ + +/***ja @brief �ޥå׷��Υ᥽�åɤ򼨤�����ܥ�. + + ����ܥ� #Mmap �� "map" �Ȥ���̾���������ʸ�����åȤ� + @b Mmethod �ѥ�᡼�����ͤȤ����Ѥ���줿���ˤϡ������ɥݥ���Ȥ�ʸ�����åȤ�ʸ�������ɤδ֤��Ѵ����ޥåפ򻲾Ȥ��뤳�Ȥˤ�äƹԤ��뤳�Ȥ��̣���롣 + �ޥåפ� @b Mmapfile �ѥ�᡼���Ȥ���Ϳ���ʤ���Фʤ�ʤ��� */ + +MSymbol Mmap; +/*=*/ + +/***en @brief Symbol for the unify type method of charset. + + The symbol #Munify has the name "unify" and, when used as + a value of @b Mmethod parameter of a charset, it means that the + conversion of code-points and character codes of the charset is + done by map looking up and offsetting. The map must be given by + @b Mmapfile parameter. For this kind of charset, a unique + continuous character code space for all characters is assigned. + + If the map has an entry for a code-point, the conversion is done + by looking up the map. Otherwise, the conversion is done by this + calculation: + +@verbatim +CHARACTER-CODE = CODE-POINT - MIN-CODE + LOWEST-CHAR-CODE +@endverbatim + + where, MIN-CODE is a value of @b Mmin_code parameter of the charset, + and LOWEST-CHAR-CODE is the lowest character code of the assigned + code space. */ + +/***ja @brief ��˥ե������Υ᥽�åɤ򼨤�����ܥ�. + + ����ܥ� #Munify �� "unify" �Ȥ���̾���������ʸ�����åȤ� + @b Mmethod �ѥ�᡼�����ͤȤ����Ѥ���줿���ˤϡ������ɥݥ���Ȥ�ʸ�����åȤ�ʸ�������ɤδ֤��Ѵ������ޥåפλ��Ȥȥ��ե��åȤ��Ȥ߹�碌�ˤ�äƹԤ��뤳�Ȥ��̣���롣 + �ޥåפ� @b Mmapfile �ѥ�᡼���Ȥ���Ϳ���ʤ���Фʤ�ʤ��� + ���μ�γ�ʸ�����åȤˤϡ���ʸ�����Ф���Ϣ³���륳���ɥ��ڡ��������줾�������Ƥ��롣 + + �����ɥݥ���Ȥ��ޥåפ˴ޤޤ�Ƥ���С��Ѵ��ϥޥå׻��Ȥˤ�äƹԤ��롣 + �����Ǥʤ���С��ʲ��μ��˽����� + +@verbatim +CHARACTER-CODE = CODE-POINT - MIN-CODE + LOWEST-CHAR-CODE +@endverbatim + + �����ǡ�MIN-CODE ��ʸ�����åȤ� @b Mmin_code �ѥ�᡼�����ͤǤ��ꡢ + LOWEST-CHAR-CODE �ϳ�����Ƥ�줿�����ɥ��ڡ����κǤ⾮����ʸ�������ɤǤ��롣 + */ + +MSymbol Munify; +/*=*/ + +/***en + @brief Symbol for the subset type method of charset. + + The symbol #Msubset has the name "subset" and, when used + as a value of @b Mmethod parameter of a charset, it means that the + charset is a subset of a parent charset. The parent charset must + be given by @b Mparents parameter. The conversion of code-points + and character codes of the charset is done conceptually by this + calculation: + +@verbatim +CHARACTER-CODE = PARENT-CODE (CODE-POINT) + SUBSET-OFFSET +@endverbatim + + where, PARENT-CODE is a pseudo function that returns a character + code of CODE-POINT in the parent charset, and SUBSET-OFFSET is a + value given by @b Msubset_offset parameter. */ + +/***ja @brief ���֥��åȷ��Υ᥽�åɤ򼨤�����ܥ�. + + ����ܥ� #Msubset �� "subset" �Ȥ���̾���������ʸ�����åȤ� + @b Mmethod �ѥ�᡼�����ͤȤ����Ѥ���줿���ˤϡ�����ʸ�����åȤ��̤�ʸ�����åȡʿ�ʸ�����åȡˤ���ʬ����Ǥ��뤳�Ȥ��̣���롣 + ��ʸ�����åȤ� @b Mparents �ѥ�᡼���ˤ�ä�Ϳ�����ʤ��ƤϤʤ�ʤ��� + �����ɥݥ���Ȥ�ʸ�����åȤ�ʸ�������ɤδ֤��Ѵ��ϡ���ǰŪ�ˤϰʲ��μ��˽����� + +@verbatim +CHARACTER-CODE = PARENT-CODE (CODE-POINT) + SUBSET-OFFSET +@endverbatim + + ������ PARENT-CODE �� CODE-POINT + �ο�ʸ�����å���Ǥ�ʸ�������ɤ��֤����ؿ��Ǥ��ꡢSUBSET-OFFSET �� + @b Msubset_offset �ѥ�᡼����Ϳ�������ͤǤ��롣 + */ + +MSymbol Msubset; +/*=*/ + +/***en + @brief Symbol for the superset type method of charset. + + The symbol #Msuperset has the name "superset" and, when + used as a value of @b Mmethod parameter of a charset, it means that + the charset is a superset of parent charsets. The parent charsets + must be given by @b Mparents parameter. */ + +/***ja + @brief �����ѡ����åȷ��Υ᥽�åɤ򼨤�����ܥ�. + + ����ܥ� #Msuperset �� "superset" �Ȥ���̾���������ʸ�����åȤ� + @b Mmethod �ѥ�᡼�����ͤȤ����Ѥ���줿���ˤϡ�����ʸ�����åȤ��̤�ʸ�����åȡʿ�ʸ�����åȡˤξ�̽���Ǥ��뤳�Ȥ��̣���롣 + ��ʸ�����åȤ� @b Mparents �ѥ�᡼���ˤ�ä�Ϳ�����ʤ��ƤϤʤ�ʤ��� + */ + +MSymbol Msuperset; +/*=*/ +/*** @} */ + +/***en + @brief Define a charset. + + The mchar_define_charset () function defines a new charset and + makes it accessible via a symbol whose name is $NAME. $PLIST + specifies parameters of the charset as below: + +
    + +
  • Key is @b Mmethod, value is a symbol. + + The value specifies the method for decoding/encoding code-points + in the charset. It must be #Moffset, #Mmap (default), #Munify, + #Msubset, or #Msuperset. + +
  • Key is @b Mdimension, value is an integer + + The value specifies the dimension of code-points of the charset. + It must be 1 (default), 2, 3, or 4. + +
  • Key is @b Mmin_range, value is an unsigned integer + + The value specifies the minimum range of a code-point, which means + that the Nth byte of the value is the minimum Nth byte of + code-points of the charset. The default value is 0. + +
  • Key is @b Mmax_range, value is an unsigned integer + + The value specifies the maximum range of a code-point, which means + that the Nth byte of the value is the maximum Nth byte of + code-points of the charset. The default value is 0xFF, 0xFFFF, + 0xFFFFFF, or 0xFFFFFFFF if the dimension is 1, 2, 3, or 4 + respectively. + +
  • Key is @b Mmin_code, value is an unsigned integer + + The value specifies the minimum code-point of + the charset. The default value is the minimum range. + +
  • Key is @b Mmax_code, value is an unsigned integer + + The value specifies the maximum code-point of + the charset. The default value is the maximum range. + +
  • Key is @b Mascii_compatible, value is a symbol + + The value specifies whether the charset is ASCII compatible or + not. If the value is #Mnil (default), it is not ASCII + compatible, else compatible. + +
  • Key is @b Mfinal_byte, value is an integer + + The value specifies the @e final @e byte of the charset registered + in The International Registry. It must be 0 (default) or 32..127. + The value 0 means that the charset is not in the registry. + +
  • Key is @b Mrevision, value is an integer + + The value specifies the @e revision @e number of the charset + registered in The International Registry. It must be 0..127. If + the charset is not in The International Registry, the value is + ignored. The value 0 means that the charset has no revision + number. + +
  • Key is @b Mmin_char, value is an integer + + The value specifies the minimum character code of the charset. + The default value is 0. + +
  • Key is @b Mmapfile, value is an M-text + + If the method is #Mmap or #Munify, a data that contains + mapping information is added to the m17n database by calling + the function mdatabase_define () with the value as an argument $EXTRA_INFO, + i.e. the value is used as a file name of the data. + + Otherwise, this parameter is ignored. + +
  • Key is @b Mparents, value is a plist + + If the method is #Msubset, the value must is a plist of length + 1, and the value of the plist must be a symbol representing a + parent charset. + + If the method is #Msuperset, the value must be a plist of length + less than 9, and the values of the plist must be symbols + representing subset charsets. + + Otherwise, this parameter is ignored. + +
  • Key is @b Mdefine_coding, value is a symbol + + If the dimension of the charset is 1, the value specifies whether + or not to define a coding system of the same name whose type is + #Mcharset. A coding system is defined if the value is not #Mnil. + + Otherwise, this parameter is ignored. + +
+ + @return + If the operation was successful, mchar_define_charset () returns a + symbol whose name is $NAME. Otherwise it returns #Mnil and + assigns an error code to the external variable #merror_code. */ + +/***ja + @brief ʸ�����åȤ��������. + + �ؿ� mchar_define_charset () �Ͽ�����ʸ�����åȤ������������� + $NAME �Ȥ���̾������ĥ���ܥ��ͳ�ǥ��������Ǥ���褦�ˤ��롣 + $PLIST ����������ʸ�����åȤΥѥ�᡼����ʲ��Τ褦�˻��ꤹ�롣 + +
    + +
  • ������ @b Mmethod ���ͤ�����ܥ�λ� + + �ͤϡ�#Moffset, #Mmap (�ǥե������), #Munify, #Msubset, + #Msuperset �Τ����줫�Ǥ��ꡢʸ�����åȤΥ����ɥݥ���Ȥ�ǥ����ɡ����󥳡��ɤ���ݤΥ᥽�åɤ���ꤹ�롣 + +
  • ������ @b Mdimension ���ͤ������ͤλ� + + �ͤϡ�1 (�ǥե������), 2, 3, 4 + �Τ����줫�Ǥ��ꡢʸ�����åȤΥ����ɥݥ���Ȥμ����Ǥ��롣 + +
  • ������ @b Mmin_range ���ͤ����������ͤλ� + + �ͤϥ����ɥݥ���ȤκǾ����ͤǤ��롣���ʤ���������ͤ� N + ���ܤΥХ��ȤϤ���ʸ�����åȤΥ����ɥݥ���Ȥ� N ���ܤΥХ��ȤκǾ��Τ�ΤȤʤ롣 + �ǥե�����ͤ� 0 �� + +
  • ������ @b Mmax_range ���ͤ����������ͤλ� + + �ͤϥ����ɥݥ���Ȥκ�����ͤǤ��롣���ʤ���������ͤ� N + ���ܤΥХ��ȤϤ���ʸ�����åȤΥ����ɥݥ���Ȥ� N ���ܤΥХ��Ȥκ���Τ�ΤȤʤ롣 + �ǥե�����ͤϡ������ɥݥ���Ȥμ����� 1, 2, 3, 4 �λ������줾�� + 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF �� + +
  • ������ @b Mmin_code ���ͤ����������ͤλ� + + �ͤϤ���ʸ�����åȤκǾ��Υ����ɥݥ���ȤǤ��롣�ǥե�����ͤ� + @b Mmin_range ���͡� + +
  • ������ @b Mmax_code ���ͤ����������ͤλ� + + �ͤϤ���ʸ�����åȤκ���Υ����ɥݥ���ȤǤ��롣�ǥե�����ͤ� + @b Mmax_range ���͡� + +
  • ������ @b Mascii_compatible ���ͤ�����ܥ�λ� + + �ͤϤ���ʸ�����åȤ� ASCII �ߴ��Ǥ��뤫�ɤ����򼨤����ǥե�����ͤ� + #Mnil �Ǥ���иߴ��ǤϤʤ�������ʳ��ξ��ϸߴ��Ǥ��롣 + +
  • ������ @b Mfinal_byte ���ͤ������ͤλ� + + �ͤϤ���ʸ�����åȤ� The International Registry ����Ͽ����Ƥ��� + @e ��ü�Х��� �Ǥ��ꡢ0 (�ǥե������) �Ǥ��뤫 32..127 �Ǥ��롣0 + ����Ͽ����Ƥ��ʤ����Ȥ��̣���롣 + +
  • ������ @b Mrevision ���ͤ������ͤλ� + + �ͤ� The International Registry ����Ͽ����Ƥ��� @e revision @e + number �Ǥ��ꡢ0..127 �Ǥ��롣 + ʸ�����åȤ���Ͽ����Ƥ��ʤ����ˤϤ����ͤ�̵�뤵��롣 + 0 �� revision number ��¸�ߤ��ʤ����Ȥ��̣���롣 + +
  • ������ @b Mmin_char ���ͤ������ͤλ� + + �ͤϤ���ʸ�����åȤκǾ���ʸ�������ɤǤ��롣�ǥե�����ͤ� 0 �� + +
  • ������ @b Mmapfile ���ͤ� M-text �λ� + + �᥽�åɤ� #Mmap �� #Munify �λ����ؿ� mdatabase_define () + �򤳤��ͤ���� $EXTRA_INFO �Ȥ��ƸƤ֤��Ȥˤ�äơ��ޥåԥ󥰤˴ؤ���ǡ����� + m17n �ǡ����١������ɲä���롣 + ���ʤ���������ͤϥǡ����ե������̾���Ǥ��롣 + + �����Ǥʤ���С����Υѥ�᡼����̵�뤵��롣 + +
  • ������ @b Mparents ���ͤ� plist �λ� + + �᥽�åɤ� #Msubset �ʤ�С��ͤ�Ĺ�� 1 �� plist + �Ǥ��ꡢ�����ͤϤ���ʸ�����åȤξ�̽���Ȥʤ�ʸ�����åȤ򼨤�����ܥ�Ǥ��롣 + + �᥽�åɤ� #Msuperset �ʤ�С��ͤ�Ĺ�� 8 �ʲ��� plist + �Ǥ��ꡢ�������ͤϤ���ʸ�����åȤβ��̽���Ǥ���ʸ�����åȤ򼨤�����ܥ�Ǥ��롣 + + �����Ǥʤ���С����Υѥ�᡼����̵�뤵��롣 + +
  • ������ @b Mdefine_coding ���ͤ�����ܥ�λ� + + ʸ�����åȤμ����� 1 �ʤ�С��ͤ� #Mnil �ʳ��ξ��� #Mcharset �� + ��Ʊ��̾������ĥ����ɷϤ�������롣 + + �����Ǥʤ���С����Υѥ�᡼����̵�뤵��롣 + +
+ + @return + ��������������С�mchar_define_charset() �� $NAME + �Ȥ���̾���Υ���ܥ���֤��������Ǥʤ���� #Mnil ���֤��������ѿ� + #merror_code �˥��顼�����ɤ����ꤹ�롣*/ + +/*** + @errors + @c MERROR_CHARSET */ + +MSymbol +mchar_define_charset (const char *name, MPlist *plist) +{ + MSymbol sym = msymbol (name); + MCharset *charset; + int i; + unsigned min_range, max_range; + MPlist *pl; + MText *mapfile = (MText *) mplist_get (plist, Mmapfile); + + MSTRUCT_CALLOC (charset, MERROR_CHARSET); + charset->name = sym; + charset->method = (MSymbol) mplist_get (plist, Mmethod); + if (! charset->method) + { + if (mapfile) + charset->method = Mmap; + else + charset->method = Moffset; + } + if (charset->method == Mmap || charset->method == Munify) + { + if (! mapfile) + MERROR (MERROR_CHARSET, Mnil); + mdatabase_define (Mcharset, sym, Mnil, Mnil, NULL, mapfile->data); + } + if (! (charset->dimension = (int) mplist_get (plist, Mdimension))) + charset->dimension = 1; + + min_range = (unsigned) mplist_get (plist, Mmin_range); + if ((pl = mplist_find_by_key (plist, Mmax_range))) + { + max_range = (unsigned) MPLIST_VAL (pl); + if (max_range >= 0x1000000) + charset->dimension = 4; + else if (max_range >= 0x10000 && charset->dimension < 3) + charset->dimension = 3; + else if (max_range >= 0x100 && charset->dimension < 2) + charset->dimension = 2; + } + else if (charset->dimension == 1) + max_range = 0xFF; + else if (charset->dimension == 2) + max_range = 0xFFFF; + else if (charset->dimension == 3) + max_range = 0xFFFFFF; + else + max_range = 0xFFFFFFFF; + + memset (charset->code_range, 0, sizeof charset->code_range); + for (i = 0; i < charset->dimension; i++, min_range >>= 8, max_range >>= 8) + { + charset->code_range[i * 4] = min_range & 0xFF; + charset->code_range[i * 4 + 1] = max_range & 0xFF; + } + if ((charset->min_code = (int) mplist_get (plist, Mmin_code)) < min_range) + charset->min_code = min_range; + if ((charset->max_code = (int) mplist_get (plist, Mmax_code)) > max_range) + charset->max_code = max_range; + charset->ascii_compatible + = (MSymbol) mplist_get (plist, Mascii_compatible) != Mnil; + charset->final_byte = (int) mplist_get (plist, Mfinal_byte); + charset->revision = (int) mplist_get (plist, Mrevision); + charset->min_char = (int) mplist_get (plist, Mmin_char); + pl = (MPlist *) mplist_get (plist, Mparents); + charset->nparents = pl ? mplist_length (pl) : 0; + if (charset->nparents > 8) + charset->nparents = 8; + for (i = 0; i < charset->nparents; i++, pl = MPLIST_NEXT (pl)) + { + MSymbol parent_name; + + if (MPLIST_KEY (pl) != Msymbol) + MERROR (MERROR_CHARSET, Mnil); + parent_name = MPLIST_SYMBOL (pl); + if (! (charset->parents[i] = MCHARSET (parent_name))) + MERROR (MERROR_CHARSET, Mnil); + } + + charset->subset_offset = (int) mplist_get (plist, Msubset_offset); + + msymbol_put (sym, Mcharset, charset); + charset = make_charset (charset); + if (! charset) + return Mnil; + msymbol_put (msymbol__canonicalize (sym), Mcharset, charset); + + for (pl = (MPlist *) mplist_get (plist, Maliases); + pl && MPLIST_KEY (pl) == Msymbol; + pl = MPLIST_NEXT (pl)) + { + MSymbol alias = MPLIST_SYMBOL (pl); + + msymbol_put (alias, Mcharset, charset); + msymbol_put (msymbol__canonicalize (alias), Mcharset, charset); + } + + if (mplist_get (plist, Mdefine_coding) + && charset->dimension == 1 + && charset->code_range[0] == 0 && charset->code_range[1] == 255) + mconv__register_charset_coding (sym); + return (sym); +} + +/*=*/ + +/***en + @brief Resolve charset name. + + The mchar_resolve_charset () function returns $SYMBOL if it + represents a charset. Otherwise, canonicalize $SYMBOL as to a + charset name, and if the canonicalized name represents a charset, + return it. Otherwise, return #Mnil. */ + +/***ja + @brief ʸ�����å�̾���褹��. + + �ؿ� mchar_resolve_charset () �� $SYMBOL + ��ʸ�����åȤ򼨤��Ƥ���Ф�����֤��� + + �����Ǥʤ���С�$SYMBOL ��ʸ�����å�̾�Ȥ����������������줬ʸ�����åȤ򼨤��Ƥ��Ƥ����������������Τ��֤��� + �����Ǥʤ���С�#Mnil ���֤��� */ + +MSymbol +mchar_resolve_charset (MSymbol symbol) +{ + MCharset *charset = (MCharset *) msymbol_get (symbol, Mcharset); + + if (! charset) + { + symbol = msymbol__canonicalize (symbol); + charset = (MCharset *) msymbol_get (symbol, Mcharset); + } + + return (charset ? charset->name : Mnil); +} + +/*=*/ + +/***en + @brief List symbols representing charsets. + + The mchar_list_charsets () function makes an array of symbols + representing a charset, stores the pointer to the array in a place + pointed to by $SYMBOLS, and returns the length of the array. */ + +/***ja + @brief ʸ�����åȤ�ɽ�魯����ܥ����󤹤�. + + �ؿ� mchar_list_charsets () + �ϡ�ʸ�����åȤ򼨤�����ܥ���¤٤�������ꡢ$SYMBOLS + �ǥݥ���Ȥ��줿���ˤ�������ؤΥݥ��󥿤��֤��������Ĺ�����֤��� */ + +int +mchar_list_charset (MSymbol **symbols) +{ + int i; + + MTABLE_MALLOC ((*symbols), charset_list.used, MERROR_CHARSET); + for (i = 0; i < charset_list.used; i++) + (*symbols)[i] = charset_list.charsets[i]->name; + return i; +} + +/*=*/ + +/***en + @brief Decode a code-point. + + The mchar_decode () function decodes code-point $CODE in the + charset represented by the symbol $CHARSET_NAME to get a character + code. + + @return + If decoding was successful, mchar_decode () returns the decoded + character code. Otherwise it returns -1. */ + +/***ja + @brief �����ɥݥ���Ȥ�ǥ����ɤ���. + + �ؿ� mchar_decode () �ϡ�����ܥ� $CHARSET_NAME �Ǽ������ʸ�����å���� + $CODE �Ȥ��������ɥݥ���Ȥ�ǥ����ɤ���ʸ�������ɤ����롣 + + @return + �ǥ����ɤ���������С�mchar_decode () �ϥǥ����ɤ��줿ʸ�������ɤ��֤��� + �����Ǥʤ���� -1 ���֤��� */ + +/*** + @seealso + mchar_encode () */ + +int +mchar_decode (MSymbol charset_name, unsigned code) +{ + MCharset *charset = MCHARSET (charset_name); + + if (! charset) + return MCHAR_INVALID_CODE; + return DECODE_CHAR (charset, code); +} + +/*=*/ + +/***en + @brief Encode a character code. + + The mchar_encode () function encodes character code $C to get a + code-point in the charset represented by the symbol $CHARSET_NAME. + + @return + If encoding was successful, mchar_encode () returns the encoded + code-point. Otherwise it returns #MCHAR_INVALID_CODE. */ + +/***ja + @brief ʸ�������ɤ򥨥󥳡��ɤ���. + + �ؿ� mchar_encode () �ϡ�ʸ�������� $C �򥨥󥳡��ɤ��ƥ���ܥ� + $CHARSET_NAME �Ǽ������ʸ�����å���ˤ����륳���ɥݥ���Ȥ����롣 + + @return + ���󥳡��ɤ���������С�mchar_encode () �ϥ��󡼥ɤ��줿�����ɥݥ���Ȥ��֤��� + �����Ǥʤ���� #MCHAR_INVALID_CODE ���֤��� */ + +/*** + @seealso + mchar_decode () */ + +unsigned +mchar_encode (MSymbol charset_name, int c) +{ + MCharset *charset = MCHARSET (charset_name); + + if (! charset) + return MCHAR_INVALID_CODE; + return ENCODE_CHAR (charset, c); +} + +/*=*/ + +/***en + @brief Call a function for all the characters in a specified charset. + + The mcharset_map_chars () function calls $FUNC for all the + characters in the charset named $CHARSET_NAME. A call is done for + a chunk of consecutive characters rather than character by + character. + + $FUNC receives three arguments: $FROM, $TO, and $ARG. $FROM and + $TO specify the range of character codes in $CHARSET. $ARG is the + same as $FUNC_ARG. + + @return + If the operation was successful, mcharset_map_chars () returns 0. + Otherwise, it returns -1 and assigns an error code to the external + variable #merror_code. */ + +/***ja + @brief ���ꤷ��ʸ�����åȤΤ��٤Ƥ�ʸ�����Ф��ƴؿ���Ƥ�. + + �ؿ� mcharset_map_chars () �� $CHARSET_NAME + �Ȥ���̾�������ʸ�����å���Τ��٤Ƥ�ʸ�����Ф��� $FUNC ��Ƥ֡� + �ƤӽФ��ϰ�ʸ����ǤϤʤ���Ϣ³����ʸ���ΤޤȤޤ�ñ�̤ǹԤʤ��롣 + + �ؿ� $FUNC �ˤ�$FROM, $TO, $ARG �Σ��������Ϥ���롣$FROM �� $TO + �� $CHARSET ���ʸ�������ɤ��ϰϤ���ꤹ�롣$ARG �� $FUNC_ARG + ��Ʊ���Ǥ��롣 + + @return + ��������������� mcharset_map_chars () �� 0 ���֤��� + �����Ǥʤ���� -1 ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_CHARSET */ + +int +mchar_map_charset (MSymbol charset_name, + void (*func) (int from, int to, void *arg), + void *func_arg) +{ + MCharset *charset; + + charset = MCHARSET (charset_name); + if (! charset) + MERROR (MERROR_CHARSET, -1); + + if (charset->encoder) + { + int c = charset->min_char; + int next_c; + + if ((int) mchartable__lookup (charset->encoder, c, &next_c, 1) < 0) + c = next_c; + while (c <= charset->max_char) + { + if ((int) mchartable__lookup (charset->encoder, c, &next_c, 1) >= 0) + (*func) (c, next_c - 1, func_arg); + c = next_c; + } + } + else + (*func) (charset->min_char, charset->max_char, func_arg); + return 0; +} + +/*=*/ + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/charset.h b/src/charset.h new file mode 100644 index 0000000..5cf9aa2 --- /dev/null +++ b/src/charset.h @@ -0,0 +1,253 @@ +/* charset.h -- header file for the charset module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_CHARSET_H_ +#define _M17N_CHARSET_H_ + +/** @file charset.h + @brief Header for charset handlers. +*/ + +enum mcharset_method + { + MCHARSET_METHOD_OFFSET, + MCHARSET_METHOD_MAP, + MCHARSET_METHOD_DEFERRED, + MCHARSET_METHOD_SUBSET, + MCHARSET_METHOD_SUPERSET, + MCHARSET_METHOD_MAX + }; + +/** Structure for charset. */ + +typedef struct MCharset MCharset; + +struct MCharset +{ + /** The value is always 0 because all charsets are static. */ + unsigned ref_count; + + /** Symbol indicating the name of the charset. */ + MSymbol name; + + /** Number of dimensions of the charset. It must be 1, 2, 3, or + 4. */ + int dimension; + + /** Byte code range of each dimension. [4N] is a + minimum byte code of the (N+1)th dimension, [4N+1] + is a maximum byte code of the (N+1)th dimension, + [4N+2] is ([4N+1] - [4N] + + 1), [4N+3] is a number of characters contained in the + first to (N+1)th dimensions. We get "char-index" of a + "code-point" from this information. */ + int code_range[16]; + + /** The minimum code-point calculated from . It may be + smaller than . */ + int code_range_min_code; + + /** Nonzero means there is no gap in code points of the charset. If + is 1, is always 1. Otherwise, + is 1 iff [4N] is zero and + [4N+1] is 256 for N = 0..-2. If + is nonzero, "char-index" is "code-point" - + . */ + int no_code_gap; + + /** If the byte code B is valid in the (N+1)th dimension, + ([B] & (1 << N)) is 1. Otherwise, + ([B] & (1 << N)) is 0. */ + unsigned char code_range_mask[256]; + + /** Minimum and maximum code-point of the charset. */ + unsigned min_code, max_code; + + /** Nonzero means the charset encodes ASCII characters as is. */ + int ascii_compatible; + + /** Minimum and maximum character of the charset. If + is nonzero, is actually the + minimum non-ASCII character of the charset. */ + int min_char, max_char; + + /** ISO 2022 final byte of the charset. It must be in the range + 48..127, or -1. The value -1 means that the charset is not + encodable by ISO 2022 based coding systems. */ + int final_byte; + + /** ISO 2022 revision number of the charset, or -1. The value -1 + means that the charset has no revision number. Used only when + is not -1. */ + int revision; + + /** Specify how to encode/decode code-point of the charset. It must + be Moffset, Mmap, Munify, Msubset, or Msuperset. */ + MSymbol method; + + /** Array of integers to decode a code-point of the charset. It is + indexed by a "char-index" of the code-point, and the + corresponding element is a character of the charset, or -1 if + the code point is not valid in the charset. Used only when + is Mmap or Munify. */ + int *decoder; + + /** Char-table to encode a character of the charset. It is indexed + by a character code, and the corresponding element is a code + point of the character in the charset, or + MCHAR_INVALID_CODE if the character is not included in the + charset. Used only when is Mmap or Munify. */ + MCharTable *encoder; + + int unified_max; + + /** Array of pointers to parent charsets. Used only when + is Msubset or Msuperset. Atmost 8 parents are supported. */ + MCharset *parents[8]; + + /* Number of parent charsets. */ + int nparents; + + unsigned subset_min_code, subset_max_code; + int subset_offset; + + int simple; + + /** If the charset is fully loaded (i.e. all the above member are + set to correct values), the value is 1. Otherwise, the value is + 0. */ + int fully_loaded; +}; + +extern MPlist *mcharset__cache; + +/** Return a charset associated with the symbol CHARSET_SYM. */ + +#define MCHARSET(charset_sym) \ + (((charset_sym) == MPLIST_KEY (mcharset__cache) \ + || (MPLIST_KEY (mcharset__cache) = (charset_sym), \ + MPLIST_VAL (mcharset__cache) \ + = (MCharset *) msymbol_get ((charset_sym), Mcharset))) \ + ? MPLIST_VAL (mcharset__cache) \ + : mcharset__find (charset_sym)) + + +/** Return index of a character whose code-point in CHARSET is CODE. + If CODE is not valid, return -1. */ + +#define CODE_POINT_TO_INDEX(charset, code) \ + ((charset)->no_code_gap \ + ? (code) - (charset)->min_code \ + : (((charset)->code_range_mask[(code) >> 24] & 0x8) \ + && ((charset)->code_range_mask[((code) >> 16) & 0xFF] & 0x4) \ + && ((charset)->code_range_mask[((code) >> 8) & 0xFF] & 0x2) \ + && ((charset)->code_range_mask[(code) & 0xFF] & 0x1)) \ + ? (((((code) >> 24) - (charset)->code_range[12]) \ + * (charset)->code_range[11]) \ + + (((((code) >> 16) & 0xFF) - (charset)->code_range[8]) \ + * (charset)->code_range[7]) \ + + (((((code) >> 8) & 0xFF) - (charset)->code_range[4]) \ + * (charset)->code_range[3]) \ + + (((code) & 0xFF) - (charset)->code_range[0]) \ + - ((charset)->min_code - (charset)->code_range_min_code)) \ + : -1) + + +/* Return code-point of a character whose index is IDX. + The validness of IDX is not checked. IDX may be modified. */ + +#define INDEX_TO_CODE_POINT(charset, idx) \ + ((charset)->no_code_gap \ + ? (idx) + (charset)->min_code \ + : (idx += (charset)->min_code - (charset)->code_range_min_code, \ + (((charset)->code_range[0] + (idx) % (charset)->code_range[2]) \ + | (((charset)->code_range[4] \ + + ((idx) / (charset)->code_range[3] % (charset)->code_range[6])) \ + << 8) \ + | (((charset)->code_range[8] \ + + ((idx) / (charset)->code_range[7] % (charset)->code_range[10])) \ + << 16) \ + | (((charset)->code_range[12] + ((idx) / (charset)->code_range[11])) \ + << 24)))) + + +/** Return a character whose code-point in CHARSET is CODE. If CODE + is invalid, return -1. */ + +#define DECODE_CHAR(charset, code) \ + (((code) < 128 && (charset)->ascii_compatible) \ + ? (int) (code) \ + : ((code) < (charset)->min_code || (code) > (charset)->max_code) \ + ? -1 \ + : ! (charset)->simple \ + ? mcharset__decode_char ((charset), (code)) \ + : (charset)->method == Moffset \ + ? (code) - (charset)->min_code + (charset)->min_char \ + : (charset)->decoder[(code) - (charset)->min_code]) + + +/** Return a code-point in CHARSET for character C. If CHARSET + does not contain C, return MCHAR_INVALID_CODE. */ + +#define ENCODE_CHAR(charset, c) \ + (! (charset)->simple \ + ? mcharset__encode_char ((charset), (c)) \ + : ((c) < (charset)->min_char || (c) > (charset)->max_char) \ + ? MCHAR_INVALID_CODE \ + : (charset)->method == Moffset \ + ? (c) - (charset)->min_char + (charset)->min_code \ + : (unsigned) mchartable_lookup ((charset)->encoder, (c))) + + +extern MCharset *mcharset__ascii; +extern MCharset *mcharset__binary; +extern MCharset *mcharset__m17n; +extern MCharset *mcharset__unicode; + +#define ISO_MAX_DIMENSION 3 +#define ISO_MAX_CHARS 2 +#define ISO_MAX_FINAL 0x80 /* only 0x30..0xFF are used */ + +typedef struct +{ + /* Table of ISO-2022 charsets. */ + int size, inc, used; + MCharset **charsets; + + /** A 3-dimensional table indexed by "dimension", "chars", and + "final byte" of an ISO-2022 charset to get the correponding + charset. A charset that has a revision number is not stored in + this table. */ + MCharset *classified[ISO_MAX_DIMENSION][ISO_MAX_CHARS][ISO_MAX_FINAL]; +} MCharsetISO2022Table; + +extern MCharsetISO2022Table mcharset__iso_2022_table; + +#define MCHARSET_ISO_2022(dim, chars, final) \ + mcharset__iso_2022_table.classified[(dim) - 1][(chars) == 96][(final)] + +extern MCharset *mcharset__find (MSymbol name); +extern int mcharset__decode_char (MCharset *charset, unsigned code); +extern unsigned mcharset__encode_char (MCharset *charset, int c); +extern int mcharset__load_from_database (); + +#endif /* _M17N_CHARSET_H_ */ diff --git a/src/chartab.c b/src/chartab.c new file mode 100644 index 0000000..d58aa65 --- /dev/null +++ b/src/chartab.c @@ -0,0 +1,1013 @@ +/* chartab.h -- character table module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nChartable + @brief Chartable objects and API for them. + + The m17n library supports enormous number of characters. Thus, if + attributes of each character are to be stored in a simple array, + such an array would be impractically big. The attributes usually + used, however, are often assigned only to a range of characters. + Even when all characters have attributes, characters of + consecutive character code tend to have the same attribute values. + + The m17n library utilizes this tendency to store characters and + their attribute values efficiently in an object called @e + Chartable. Although a chartable object is not a simple array, + application programs can handle a chartable as if it is an array. + Attribute values of a character can be obtained by accessing a + Chartable for the attribute with the character code of the + specified character. + + A chartable is a managed object. */ + +/***ja + @addtogroup m17nChartable ʸ���ơ��֥� + + @brief ʸ���ơ��֥�Ȥ���˴ؤ��� API. + + m17n �饤�֥�꤬����ʸ���ζ��֤Ϲ���Ǥ��뤿�ᡢʸ����ξ����ñ�������˳�Ǽ���褦�Ȥ���ȡ���������ϵ���ˤʤꤹ���������Ū�Ǥ��롣 + �������̾�ɬ�פȤʤ�ʸ���ˤĤ��Ƥξ���ϡ�����������ϰϤ�ʸ���ˤΤ��դ��Ƥ��뤳�Ȥ�¿���� + ��ʸ���˴ؤ��ƾ��󤬤�����ˤ⡢Ϣ³����ʸ�������ɤ����ʸ����Ʊ���������Ĥ��Ȥ�¿���� + + ���Τ褦�ʷ��������Ѥ���ʸ���Ȥ����ղþ�����ΨŪ�˳�Ǽ���뤿��ˡ� + m17n �饤�֥��� @e ʸ���ơ��֥� (chartable) �ȸƤ֥��֥������Ȥ��Ѥ��롣 + ʸ���ơ��֥������ǤϤʤ��������ץꥱ�������ץ�������ʸ���ơ��֥������ΰ��Ȥ��ư������Ȥ��Ǥ��롣 + ����ʸ���ˤĤ��Ƥ�����ξ���ϡ����ξ�������ʸ���ơ��֥�򤽤�ʸ���Υ����ɤǰ������� + �������롣 + + ʸ���ơ��֥�ϴ��������֥������ȤǤ��롣 */ + +/*=*/ +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include +#include +#include +#include + +#include "m17n.h" +#include "m17n-misc.h" +#include "internal.h" +#include "symbol.h" + +static M17NObjectArray chartable_table; + +/*** Maximum depth of char-table. */ +#define CHAR_TAB_MAX_DEPTH 3 + +/** @name Define: Number of characters covered by char-table of each level. + @{ */ + +/** BITs for number of characters covered by char-table of each + level. */ +#if MCHAR_MAX < 0x400000 + +#define SUB_BITS_0 22 /* i.e. 0x400000 chars */ +#define SUB_BITS_1 16 /* i.e. 0x10000 chars */ +#define SUB_BITS_2 12 /* i.e. 0x1000 chars */ +#define SUB_BITS_3 7 /* i.e. 0x80 chars */ + +#else /* MCHAR_MAX >= 0x400000 */ + +#define SUB_BITS_0 31 +#define SUB_BITS_1 24 +#define SUB_BITS_2 16 +#define SUB_BITS_3 8 +#endif + +/** @} */ + +/** How many characters a char-table covers at each level. */ +static const int chartab_chars[] = + { (1 << SUB_BITS_0), + (1 << SUB_BITS_1), + (1 << SUB_BITS_2), + (1 << SUB_BITS_3) }; + +/** How many slots a char-table has at each level. */ +static const int chartab_slots[] = + { (1 << (SUB_BITS_0 - SUB_BITS_1)), + (1 << (SUB_BITS_1 - SUB_BITS_2)), + (1 << (SUB_BITS_2 - SUB_BITS_3)), + (1 << SUB_BITS_3) }; + +/** Mask bits to obtain the valid bits from a character code for looking + up a char-table of each level. */ +static const int chartab_mask[] = + { (int) ((((unsigned) 1) << SUB_BITS_0) - 1), + (1 << SUB_BITS_1) - 1, + (1 << SUB_BITS_2) - 1, + (1 << SUB_BITS_3) - 1 }; + +/** Bit-shifting counts to obtain a valid index from a character code + for looking up a char-table of each level. */ +static const int chartab_shift[] = + { SUB_BITS_1, SUB_BITS_2, SUB_BITS_3, 0 }; + + +/** Index for looking up character C in a char-table at DEPTH. */ +#define SUB_IDX(depth, c) \ + (((c) & chartab_mask[depth]) >> chartab_shift[depth]) + + +/** Structure of sub char-table. */ +typedef struct MSubCharTable MSubCharTable; + +struct MSubCharTable +{ +#if SUB_BITS_0 > 24 + + /* The depth of the table; 0, 1, 2, or 3. */ + int depth; + + /* The minimum character covered by the table. */ + int min_char; + +#else /* SUB_BITS_0 <= 24 */ + + /* The value is (( << 24) | ). */ + int depth_min_char; + +#endif /* SUB_BITS_0 <= 24 */ + + /** The default value of characters covered by the table. */ + void *default_value; + + /** For a table of bottom level, array of values. For a non-bottom + table, array of sub char-tables. It may be NULL if all + characters covered by the table has . */ + union { + void **values; + MSubCharTable *tables; + } contents; +}; + +#if SUB_BITS_0 > 24 +#define TABLE_DEPTH(table) ((table)->depth) +#define TABLE_MIN_CHAR(table) ((table)->min_char) +#define SET_DEPTH_MIN_CHAR(table, DEPTH, MIN_CHAR) \ + ((table)->depth = (DEPTH), (table)->min_char = (MIN_CHAR)) +#else /* SUB_BITS_0 <= 24 */ +#define TABLE_DEPTH(table) ((table)->depth_min_char >> 24) +#define TABLE_MIN_CHAR(table) ((table)->depth_min_char & 0xFFFFFF) +#define SET_DEPTH_MIN_CHAR(table, DEPTH, MIN_CHAR) \ + ((table)->depth_min_char = ((DEPTH) << 24) | (MIN_CHAR)) +#endif /* SUB_BITS_0 <= 24 */ + +/** Structure of char-table. */ + +struct MCharTable +{ + /** Common header for a managed object. */ + M17NObject control; + + /** Key of the table. */ + MSymbol key; + + /** The minimum and maximum characters covered by the table. */ + int min_char, max_char; + + MSubCharTable subtable; +}; + + + + +/* Local functions. */ + +/** Allocate and initialize an array of sub-tables for sub char-table + TABLE. It is assumed that TABLE_DEPTH (TABLE) < + CHAR_TAB_MAX_DEPTH.*/ + +static void +make_sub_tables (MSubCharTable *table, int managedp) +{ + int depth = TABLE_DEPTH (table); + int min_char = TABLE_MIN_CHAR (table); + int slots = chartab_slots[depth]; + int chars = chartab_chars[depth + 1]; + MSubCharTable *tables; + int i; + + MTABLE_MALLOC (tables, slots, MERROR_CHARTABLE); + + for (i = 0; i < slots; i++, min_char += chars) + { + SET_DEPTH_MIN_CHAR (tables + i, depth + 1, min_char); + tables[i].default_value = table->default_value; + tables[i].contents.tables = NULL; + } + if (managedp && table->default_value) + M17N_OBJECT_REF_NTIMES (tables->default_value, slots); + table->contents.tables = tables; +} + + +/** Allocate and initialize an array of values for sub char-table + TABLE. It is assumed that TABLE_DEPTH (TABLE) == + CHAR_TAB_MAX_DEPTH. */ + +static void +make_sub_values (MSubCharTable *table, int managedp) +{ + int slots = chartab_slots[CHAR_TAB_MAX_DEPTH]; + void **values; + int i; + + MTABLE_MALLOC (values, slots, MERROR_CHARTABLE); + + for (i = 0; i < slots; i++) + values[i] = table->default_value; + if (managedp && table->default_value) + M17N_OBJECT_REF_NTIMES (table->default_value, slots); + table->contents.values = values; +} + + +/** Free contents of sub char-table TABLE and the default value of + TABLE. Free also the sub-tables recursively. */ + +static void +free_sub_tables (MSubCharTable *table, int managedp) +{ + int depth = TABLE_DEPTH (table); + int slots = chartab_slots[depth]; + + if (table->contents.tables) + { + if (depth < CHAR_TAB_MAX_DEPTH) + { + while (slots--) + free_sub_tables (table->contents.tables + slots, managedp); + free (table->contents.tables); + } + else + { + if (managedp) + while (slots--) + { + if (table->contents.values[slots]) + M17N_OBJECT_UNREF (table->contents.values[slots]); + } + free (table->contents.values); + } + table->contents.tables = NULL; + } + if (managedp && table->default_value) + M17N_OBJECT_UNREF (table->default_value); +} + + +/** In sub char-table TABLE, set value VAL for characters of the range + FROM and TO. */ + +static void +set_chartable_range (MSubCharTable *table, int from, int to, void *val, + int managedp) +{ + int depth = TABLE_DEPTH (table); + int min_char = TABLE_MIN_CHAR (table); + int max_char = min_char + (chartab_chars[depth] - 1); + int i; + + if (max_char < 0 || max_char > MCHAR_MAX) + max_char = MCHAR_MAX; + + if (from < min_char) + from = min_char; + if (to > max_char) + to = max_char; + + if (from == min_char && to == max_char) + { + free_sub_tables (table, managedp); + if (managedp && val) + M17N_OBJECT_REF (val); + table->default_value = val; + return; + } + + if (depth < CHAR_TAB_MAX_DEPTH) + { + if (! table->contents.tables) + make_sub_tables (table, managedp); + i = SUB_IDX (depth, from); + table = table->contents.tables + i; + while (i < chartab_slots[depth] && TABLE_MIN_CHAR (table) <= to) + { + set_chartable_range (table, from, to, val, managedp); + table++, i++; + } + } + else + { + int idx_from = SUB_IDX (depth, from); + int idx_to = SUB_IDX (depth, to); + + if (! table->contents.values) + make_sub_values (table, managedp); + for (i = idx_from; i <= idx_to; i++) + { + if (managedp && table->contents.values[i]) + M17N_OBJECT_UNREF (table->contents.values[i]); + table->contents.values[i] = val; + } + if (managedp && val) + M17N_OBJECT_REF_NTIMES (val, (idx_to - idx_from + 1)); + } +} + + +/** Lookup the sub char-table TABLE for the character C. If NEXT_C is + not NULL, set *NEXT_C to the next interesting character to lookup + for. If DEFAULT_P is zero, the next interesting character is what + possibly has the different value than C. Otherwise, the next + interesting character is what possibly has the default value (if C + has a value deferent from the default value) or has a value + different from the default value (if C has the default value). */ + +static void * +lookup_chartable (MSubCharTable *table, int c, int *next_c, int default_p) +{ + int depth = TABLE_DEPTH (table); + void *val; + void *default_value = table->default_value; + int idx; + + while (1) + { + if (! table->contents.tables) + { + if (next_c) + *next_c = TABLE_MIN_CHAR (table) + chartab_chars[depth]; + return table->default_value; + } + if (depth == CHAR_TAB_MAX_DEPTH) + break; + table = table->contents.tables + SUB_IDX (depth, c); + depth++; + } + + idx = SUB_IDX (depth, c); + val = table->contents.values[idx]; + + if (next_c) + { + int max_char = TABLE_MIN_CHAR (table) + (chartab_chars[depth] - 1); + + if (max_char < 0 || max_char > MCHAR_MAX) + max_char = MCHAR_MAX; + if (default_p && val != default_value) + { + do { c++, idx++; } + while (c >= 0 && c <= max_char + && table->contents.values[idx] != default_value); + } + else + { + do { c++, idx++; } + while (c >= 0 && c <= max_char + && table->contents.values[idx] == val); + } + *next_c = c; + } + return val; +} + +/** Call FUNC for characters in sub char-table TABLE. Ignore such + characters that has a value IGNORE. FUNC is called with four + arguments; FROM, TO, VAL, and ARG (same as FUNC_ARG). If + DEFAULT_P is zero, FROM and TO are range of characters that has + the same value VAL. Otherwise, FROM and TO are range of + characters that has the different value than the default value of + TABLE. */ + +static void +map_chartable (MSubCharTable *table, void *ignore, int default_p, + void (*func) (int, int, void *, void *), + void *func_arg) +{ + void *current; + int from = 0; + int c, next_c; + + current = lookup_chartable (table, 0, &next_c, default_p); + c = next_c; + while (c >= 0 && c <= MCHAR_MAX) + { + void *next = lookup_chartable (table, c, &next_c, default_p); + + if (current != next) + { + if (current != ignore) + (*func) (from, c - 1, current, func_arg); + current = next; + from = c; + } + c = next_c; + } + if (from <= MCHAR_MAX && current != ignore) + (*func) (from, MCHAR_MAX, current, func_arg); +} + + +/* Return the smallest character whose value is not DEFAULT_VALUE in + TABLE. If all characters in TABLE have DEFAULT_VALUE, return + -1. */ + +static int +chartab_min_non_default_char (MSubCharTable *table, void *default_value) +{ + int depth = TABLE_DEPTH (table); + int slots; + int i, c; + + if (!table->contents.tables) + return (default_value == table->default_value + ? -1 : TABLE_MIN_CHAR (table)); + + slots = chartab_slots[depth]; + + if (depth == CHAR_TAB_MAX_DEPTH) + { + for (i = 0; i < slots; i++) + if (table->contents.values[i] != default_value) + return (TABLE_MIN_CHAR (table) + i); + } + else + { + for (i = 0; i < slots; i++) + if ((c = chartab_min_non_default_char (table->contents.tables + i, + default_value)) + >= 0) + return c; + } + return -1; +} + + +/* Return the largest character whose value is not DEFAULT_VALUE in + TABLE. If all characters in TABLE have DEFAULT_VALUE, return + -1. */ + +static int +chartab_max_non_default_char (MSubCharTable *table, void *default_value) +{ + int depth = TABLE_DEPTH (table); + int slots; + int i, c; + + if (!table->contents.tables) + return (default_value == table->default_value + ? -1 : TABLE_MIN_CHAR (table) + chartab_chars[depth] - 1); + + slots = chartab_slots[depth]; + + if (depth == CHAR_TAB_MAX_DEPTH) + { + for (i = slots - 1; i >= 0; i--) + if (table->contents.values[i] != default_value) + return (TABLE_MIN_CHAR (table) + i); + } + else + { + for (i = slots - 1; i >= 0; i--) + if ((c = chartab_max_non_default_char (table->contents.tables + i, + default_value)) + >= 0) + return c; + } + return -1; +} + +static void +free_chartable (void *object) +{ + MCharTable *table = (MCharTable *) object; + int managedp = table->key != Mnil && table->key->managing_key; + + if (table->subtable.contents.tables) + { + int i; + + for (i = 0; i < chartab_slots[0]; i++) + free_sub_tables (table->subtable.contents.tables + i, managedp); + free (table->subtable.contents.tables); + if (managedp && table->subtable.default_value) + M17N_OBJECT_UNREF (table->subtable.default_value); + } + M17N_OBJECT_UNREGISTER (chartable_table, table); + free (object); +} + +#include + +/* Support function of mdebug_dump_chartab. */ + +static void +dump_sub_chartab (MSubCharTable *table, void *default_value, + MSymbol key, int indent) +{ + int depth = TABLE_DEPTH (table); + int min_char = TABLE_MIN_CHAR (table); + int max_char = min_char + (chartab_chars[depth] - 1); + char *prefix = (char *) alloca (indent + 1); + int i; + + if (max_char < 0 || max_char > MCHAR_MAX) + max_char = MCHAR_MAX; + + memset (prefix, 32, indent); + prefix[indent] = 0; + + if (! table->contents.tables && table->default_value == default_value) + return; + fprintf (mdebug__output, "\n%s(sub%d (U+%04X U+%04X) ", + prefix, depth, min_char, max_char); + if (key == Msymbol) + { + if (table->default_value) + fprintf (mdebug__output, "(default %s)", + ((MSymbol) table->default_value)->name); + else + fprintf (mdebug__output, "(default nil)"); + } + else + fprintf (mdebug__output, "(default #x%X)", (unsigned) table->default_value); + + default_value = table->default_value; + if (table->contents.tables) + { + if (depth < CHAR_TAB_MAX_DEPTH) + for (i = 0; i < chartab_slots[depth]; i++) + dump_sub_chartab (table->contents.tables + i, default_value, + key, indent + 2); + else + for (i = 0; i < chartab_slots[depth]; i++, min_char++) + { + void **val = table->contents.values + i; + + if (val == default_value) + continue; + default_value = *val; + fprintf (mdebug__output, "\n%s (U+%04X", prefix, min_char); + while (i + 1 < chartab_slots[depth] + && val[1] == default_value) + i++, val++, min_char++; + fprintf (mdebug__output, "-U+%04X ", min_char); + if (key == Msymbol) + { + if (default_value) + fprintf (mdebug__output, "%s)", + ((MSymbol) default_value)->name); + else + fprintf (mdebug__output, "nil)"); + } + else + fprintf (mdebug__output, " #xx%X)", (unsigned) default_value); + } + } + fprintf (mdebug__output, ")"); +} + + +/* Internal API */ + +int +mchartable__init () +{ + M17N_OBJECT_ADD_ARRAY (chartable_table, "Chartable"); + return 0; +} + +void +mchartable__fini () +{ +} + +void * +mchartable__lookup (MCharTable *table, int c, int *next_c, int default_p) +{ + return lookup_chartable (&table->subtable, c, next_c, default_p); +} + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/* External API */ + +/*** @addtogroup m17nChartable */ +/*** @{ */ +/*=*/ + +/***en + @brief Symbol whose name is "char-table". + + The symbol @c Mchar_table has the name "char-table". */ + +/***ja + @brief "char-table" �Ȥ���̾������ĥ���ܥ�. + + ����ܥ� @c Mchar_table ��̾�� "char-table" ����ġ� + */ + +MSymbol Mchar_table; + +/*=*/ + +/***en + @brief Create a new chartable. + + The mchartable () function creates a new chartable object with + symbol $KEY and the default value $DEFAULT_VALUE. If $KEY is a + managing key, the elements of the table (including the default + value) are managed objects or NULL. + + @return + If the operation was successful, mchartable () returns a pointer + to the created chartable. Otherwise it returns @c NULL and + assigns an error code to the external variable #merror_code. */ + +/***ja + @brief ������ʸ���ơ��֥����. + + �ؿ� mchartable () �ϥ����� $KEY �����ǤΥǥե�����ͤ� + $DEFAULT_VALUE �Ǥ��뿷����ʸ���ơ��֥���롣�⤷ $KEY + �����������Ǥ���С����Υơ��֥�����Ǥϡʥǥե�����ͤ�ޤ�ơ˴��������֥������Ȥ� + NULL �Τ����줫�Ǥ��롣 + + @return + ��������������� mchartable () �Ϻ������줿ʸ���ơ��֥�ؤΥݥ��󥿤��֤��� + ���Ԥ������� @c NULL ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +MCharTable * +mchartable (MSymbol key, void *default_value) +{ + MCharTable *table; + + M17N_OBJECT (table, free_chartable, MERROR_CHARTABLE); + M17N_OBJECT_REGISTER (chartable_table, table); + table->key = key; + table->min_char = -1; + table->max_char = -1; + SET_DEPTH_MIN_CHAR (&table->subtable, 0, 0); + table->subtable.default_value = default_value; + if (key != Mnil && key->managing_key && default_value) + M17N_OBJECT_REF (default_value); + table->subtable.contents.tables = NULL; + return table; +} + +/*=*/ + +/***en + @brief Return the minimum character whose value is set in a chartabe. + + The mchartable_min_char () function return the minimum character + whose value is set in chartable $TABLE. No character is set its + value, the function returns -1. + */ + +int +mchartable_min_char (MCharTable *table) +{ + return table->min_char; +} + +/*=*/ + +/***en + @brief Return the maximum character whose value is set in a chartabe. + + The mchartable_max_char () function return the maximum character + whose value is set in chartable $TABLE. No character is set its + value, the function returns -1. + */ + +int +mchartable_max_char (MCharTable *table) +{ + return table->max_char; +} + +/*=*/ + +/***en + @brief Return the assigned value of a character in a chartable. + + The mchartable_lookup () function returns the value assigned to + character $C in chartable $TABLE. If no value has been set for $C + explicitly, the default value of $TABLE is returned. If $C is not + a valid character, mchartable_lookup () returns @c NULL and + assigns an error code to the external variable #merror_code. */ + +/***ja + @brief ʸ���ơ��֥����ʸ���˳�����Ƥ�줿�ͤ��֤�. + + �ؿ� mchartable_lookup () ��ʸ���ơ��֥� $TABLE ���ʸ�� $C + �˳�����Ƥ�줿�ͤ��֤���$C ���Ф�������Ū���ͤ��ʤ���С�$TABLE + �Υǥե�����ͤ��֤���$C ��������ʸ���Ǥʤ���С�mchartable_lookup () �� + @c NULL ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_CHAR + + @seealso + mchartable_set () */ + +void * +mchartable_lookup (MCharTable *table, int c) +{ + M_CHECK_CHAR (c, NULL); + + if (c < table->min_char || c > table->max_char) + return table->subtable.default_value; + return lookup_chartable (&table->subtable, c, NULL, 0); +} + +/*=*/ + +/***en + @brief Assign a value to a character in a chartable. + + The mchartable_set () function sets the value of character $C in + chartable $TABLE to $VAL. + + @return + If the operation was successful, mchartable_set () returns 0. + Otherwise it returns -1 and assigns an error code to the external + variable #merror_code. */ + +/***ja + @brief ʸ���ơ��֥���Ǥ�ʸ�����ͤ����ꤹ��. + + �ؿ� mchartable_set () �ϡ�ʸ���ơ��֥� $TABLE ���ʸ�� $C + ���� $VAL �������Ƥ롣 + + @return + ��������������С�mchartable_set () �� 0 ���֤��������Ǥʤ���� -1 + ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_CHAR + + @seealso + mchartable_lookup (), mchartable_set_range () */ + + +int +mchartable_set (MCharTable *table, int c, void *val) +{ + int managedp = table->key != Mnil && table->key->managing_key; + MSubCharTable *sub = &table->subtable; + int i; + + M_CHECK_CHAR (c, -1); + + if (table->max_char < 0) + table->min_char = table->max_char = c; + else + { + if (c < table->min_char) + table->min_char = c; + else if (c > table->max_char) + table->max_char = c; + } + + for (i = 0; i < CHAR_TAB_MAX_DEPTH; i++) + { + if (! sub->contents.tables) + { + if (sub->default_value == val) + return 0; + make_sub_tables (sub, managedp); + } + sub = sub->contents.tables + SUB_IDX (i, c); + } + if (! sub->contents.values) + { + if (sub->default_value == val) + return 0; + make_sub_values (sub, managedp); + } + sub->contents.values[SUB_IDX (3, c)] = val; + if (managedp && val) + M17N_OBJECT_REF (val); + return 0; +} + +/*=*/ + +/***en + @brief Assign a value to the characters in the specified range. + + The mchartable_set_range () function assigns value $VAL to the + characters from $FROM to $TO (both inclusive) in chartable $TABLE. + + @return + If the operation was successful, mchartable_set_range () returns + 0. Otherwise it returns -1 and assigns an error code to the + external variable #merror_code. If $FROM is greater than $TO, + mchartable_set_range () returns immediately without an error. */ + +/***ja + @brief �����ϰϤ�ʸ�����ͤ����ꤹ��. + + �ؿ� mchartable_set_range () �ϡ�ʸ���ơ��֥� $TABLE ��� $FROM + ���� $TO �ޤǡ�ξü��ޤ�ˤ�ʸ���ˡ��ͤȤ��� $VAL �����ꤹ�롣 + + @return + ��������������� mchartable_set_range () �� 0 ���֤��������Ǥʤ���� + -1 ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣$FROM �� + $TO ����礭���Ȥ��ˤϡ� mchartable_set_range () + �ϲ��⤻�������顼�ⵯ�����ʤ��� */ + +/*** + @errors + @c MERROR_CHAR + + @seealso + mchartable_set () */ + +int +mchartable_set_range (MCharTable *table, int from, int to, void *val) +{ + int managedp = table->key != Mnil && table->key->managing_key; + + M_CHECK_CHAR (from, -1); + M_CHECK_CHAR (to, -1); + + if (from > to) + return 0; + + if (table->max_char < 0) + table->min_char = from, table->max_char = to; + else{ + if (from < table->min_char) + table->min_char = from; + if (to > table->max_char) + table->max_char = to; + } + set_chartable_range (&table->subtable, from, to, val, managedp); + return 0; +} + +/*=*/ + +/***en + @brief Search for characters that have non-default value. + + The mchartable_range () function searches chartable $TABLE for the + first and the last character codes that do not have the default + value of $TABLE, and set $FROM and $TO to them, respectively. If + all characters have the default value, both $FROM and $TO are set + to -1. */ + +/***ja + @brief �ͤ��ǥե���ȤȰۤʤ�ʸ����õ��. + + �ؿ� mchartable_range () ��ʸ���ơ��֥� $TABLE ��ǡ�$TABLE + �Υǥե�����Ͱʳ����ͤ���ĺǽ�ȺǸ��ʸ����õ�������줾��� $FROM + �� $TO �����ꤹ�롣���٤Ƥ�ʸ�����ͤȤ��ƥǥե�����ͤ�ȤäƤ�����ˤ� + $FROM �� $TO �� -1�����ꤹ�롣 */ + +void +mchartable_range (MCharTable *table, int *from, int *to) +{ + *from = chartab_min_non_default_char (&table->subtable, + table->subtable.default_value); + if (*from == -1) + *to = -1; + else + *to = chartab_max_non_default_char (&table->subtable, + table->subtable.default_value); +} + +/*=*/ + +/***en + @brief Call a function for characters in a chartable. + + The mchartable_map () function calls function $FUNC for characters + in chartable $TABLE. No function call occurs for characters that + have value $IGNORE in $TABLE. Comparison of $IGNORE and character + value is done with the operator @c ==. Be careful when you use + string literals or pointers. + + Instead of calling $FUNC for each character, mchartable_map () + tries to optimize the number of function calls, i.e. it makes a + single function call for a chunk of characters when those + consecutive characters have the same value. + + No matter how long the character chunk is, $FUNC is called with + four arguments; $FROM, $TO, $VAL, and $ARG. $FROM and $TO (both + inclusive) defines the range of characters that have value $VAL. + $ARG is the same as $FUNC_ARG. + + @return + This function always returns 0. */ + +/***ja + @brief ʸ���ơ��֥����ʸ�����Ф��ƻ���δؿ���Ƥ�. + + �ؿ� mchartable_map () �ϡ�ʸ���ơ��֥� $TABLE ���ʸ�����Ф��ƴؿ� + $FUNC ��Ƥ֡�������$TABLE ��Ǥ��ͤ� $IGNORE + �Ǥ���ʸ���ˤĤ��Ƥϴؿ��ƤӽФ���Ԥʤ�ʤ���$IGNORE ��ʸ�����ͤ���Ӥ� + @c == �ǹԤʤ��Τǡ�ʸ�����ƥ���ݥ��󥿤�Ȥ��ݤˤ����դ��פ��롣 + + mchartable_map () �ϡ���ʸ�����Ȥ� $FUNC + ��Ƥ֤ΤǤϤʤ����ؿ��ƤӽФ��β�����Ŭ�����褦�Ȥ��롣 + ���ʤ����Ϣ³����ʸ����Ʊ���ͤ���äƤ������ˤϡ�����ʸ���ΤޤȤޤ����ΤˤĤ��ư��٤δؿ��Ƥӽ� + �������Ԥʤ�ʤ��� + + ʸ���ΤޤȤޤ���礭���ˤ�����餺��$FUNC �� $FROM, $TO, $VAL, $ARG + �Σ������ǸƤФ�롣$FROM �� $TO ��ξü��ޤ�ˤ� $VAL + ���ͤȤ��ƻ���ʸ�����ϰϤ򼨤���$ARG �� $FUNC_ARG ���Τ�ΤǤ��롣 + + @return + ���δؿ��Ͼ��0���֤��� */ + +int +mchartable_map (MCharTable *table, void *ignore, + void (*func) (int, int, void *, void *), + void *func_arg) +{ + map_chartable (&table->subtable, ignore, 0, func, func_arg); + return 0; +} + +/*=*/ + +/*** @} */ + +/*** @addtogroup m17nDebug */ +/*=*/ +/*** @{ */ + +/***en + @brief Dump a chartable. + + The mdebug_dump_chartab () function prints a chartable $TABLE in a + human readable way to the stderr or to what specified by the + environment variable MDEBUG_OUTPUT_FILE. $INDENT specifies how + many columns to indent the lines but the first one. + + @return + This function returns $TABLE. */ + +/***ja + @brief ʸ���ơ��֥�����פ���. + + �ؿ� mdebug_dump_chartab () ��ʸ���ơ��֥� $TABLE ��ɸ�२�顼���� + �⤷���ϴĶ��ѿ� MDEBUG_DUMP_FONT �ǻ��ꤵ�줿�ե�����˿ʹ֤˲��� + �ʷ��ǰ������롣$INDENT �ϣ����ܰʹߤΥ���ǥ�Ȥ���ꤹ�롣 + + @return + ���δؿ��� $TABLE ���֤��� */ + +MCharTable * +mdebug_dump_chartab (MCharTable *table, int indent) +{ + fprintf (mdebug__output, "(chartab (U+%04X U+%04X)", + table->min_char, table->max_char); + dump_sub_chartab (&table->subtable, table->subtable.default_value, + table->key, indent + 2); + fprintf (mdebug__output, ")"); + return table; +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/chartab.h b/src/chartab.h new file mode 100644 index 0000000..2f97e30 --- /dev/null +++ b/src/chartab.h @@ -0,0 +1,30 @@ +/* chartab.h -- header file for the character table module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_CHARTAB_H_ +#define _M17N_CHARTAB_H_ + +extern void *mchartable__lookup (MCharTable *table, int c, + int *next_c, int default_p); + +#endif /* not _M17N_CHARTAB_H_ */ + diff --git a/src/coding.c b/src/coding.c new file mode 100644 index 0000000..fed9f89 --- /dev/null +++ b/src/coding.c @@ -0,0 +1,5078 @@ +/* coding.c -- code conversion module. + Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nConv + @brief Coding system objects and API for them. + + The m17n library represents a character encoding scheme (CES) of + coded character sets (CCS) as an object called @e coding @e + system. Application programs can add original coding systems. + + To @e encode means converting code-points to character codes and + to @e decode means converting character codes back to code-points. + + Application programs can decode a byte sequence with a specified + coding system into an M-text, and inversely, can encode an M-text + into a byte sequence. */ + +/***ja + @addtogroup m17nConv + @brief �����ɷϥ��֥������ȤȤ���˴ؤ��� API. + + m17n �饤�֥��ϡ���沽ʸ������ (coded character set; CCS) + ��ʸ����粽���� (character encoding scheme; CES) �� @e �����ɷ� + �ȸƤ֥��֥������Ȥ�ɽ�����롣 + ���ץꥱ�������ץ��������ȼ��˥����ɷϤ��ɲä��뤳�Ȥ�Ǥ��롣 + + �����ɥݥ���Ȥ���ʸ�������ɤؤ��Ѵ��� @e ���󥳡��� + �ȸƤӡ�ʸ�������ɤ��饳���ɥݥ���Ȥؤ��Ѵ��� @e �ǥ����� �ȸƤ֡� + + ���ץꥱ�������ץ������ϡ����ꤵ�줿�����ɷϤǥХ������ǥ����ɤ��뤳�Ȥˤ�ä� + M-text �����뤳�Ȥ��Ǥ��롣�ޤ��դˡ����ꤵ�줿�����ɷϤ� M-text + �򥨥󥳡��ɤ����뤳�Ȥˤ�äƥХ���������뤳�Ȥ��Ǥ��롣 */ + +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "m17n.h" +#include "m17n-misc.h" +#include "internal.h" +#include "plist.h" +#include "character.h" +#include "charset.h" +#include "coding.h" +#include "mtext.h" +#include "symbol.h" +#include "mlocale.h" + +#define NUM_SUPPORTED_CHARSETS 32 + +/** Structure for coding system object. */ + +typedef struct +{ + /** Name of the coding system. */ + MSymbol name; + + /** Type of the coding system. */ + MSymbol type; + + /* Number of supported charsets. */ + int ncharsets; + + /** Array of supported charsets. */ + MCharset *charsets[NUM_SUPPORTED_CHARSETS]; + + /** If non-NULL, function to call at the time of creating and + reseting a converter. */ + int (*resetter) (MConverter *converter); + + int (*decoder) (const unsigned char *str, int str_bytes, MText *mt, + MConverter *converter); + + int (*encoder) (MText *mt, int from, int to, + unsigned char *str, int str_bytes, + MConverter *converter); + + /** If non-zero, the coding system decode/encode ASCII characters as + is. */ + int ascii_compatible; + + /** Pointer to extra information given when the coding system is + defined. The meaning depends on . */ + void *extra_info; + + /** Pointer to information referred on conversion. The meaning + depends on . The value NULL means that the coding system + is not yet setup. */ + void *extra_spec; + + int ready; +} MCodingSystem; + +struct MCodingList +{ + int size, inc, used; + MCodingSystem **codings; +}; + +static struct MCodingList coding_list; + +static MPlist *coding_definition_list; + +typedef struct { + /**en + Pointer to a structure of a coding system. */ + /**ja + �����ɷϤ�ɽ�魯�ǡ�����¤�ؤΥݥ��� */ + MCodingSystem *coding; + + /**en + Buffer for carryover bytes generated while decoding. */ + /**ja + �ǥ�������Υ���ꥣ�����С��Х����ѥХåե� */ + unsigned char carryover[256]; + + /**en + Number of carryover bytes. */ + /**ja + ����ꥣ�����С��Х��ȿ� */ + int carryover_bytes; + + /**en + Beginning of the byte sequence bound to this converter. */ + /**ja + ���Υ���С����˷���դ���줿�Х��������Ƭ���� */ + union { + const unsigned char *in; + unsigned char *out; + } buf; + + /**en + Size of buf. */ + /**ja + buf ���礭�� */ + int bufsize; + + /**en + Number of bytes already consumed in buf. */ + /**ja + buf ��Ǥ��Ǥ˾��񤵤줿�Х��ȿ� */ + int used; + + /**en + Stream bound to this converter. */ + /**ja + ���Υ���С����˷���դ���줿���ȥ꡼�� */ + FILE *fp; + + /**en + Which of above two is in use. */ + /**ja + �嵭2�ԤΤ����줬�Ȥ��Ƥ��뤫 */ + int binding; + + /**en + Buffer for unget. */ + /**ja + Unget �ѥХåե� */ + MText *unread; + + /**en + Working area. */ + /**ja + ����ΰ� */ + MText *work_mt; + + int seekable; +} MConverterStatus; + + + +/* Local macros and functions. */ + +/** At first, set SRC_BASE to SRC. Then check if we have already + produced AT_MOST chars. If so, set SRC_END to SRC, and jump to + source_end. Otherwise, get one more byte C from SRC. In that + case, if SRC == SRC_END, jump to the label source_end. */ + +#define ONE_MORE_BASE_BYTE(c) \ + do { \ + src_base = src; \ + if (nchars == at_most) \ + { \ + src_end = src; \ + goto source_end; \ + } \ + if (src == src_stop) \ + { \ + if (src == src_end) \ + goto source_end; \ + src_base = src = source; \ + if (src == src_end) \ + goto source_end; \ + src_stop = src_end; \ + } \ + (c) = *src++; \ + } while (0) + + +/** Get one more byte C from SRC. If SRC == SRC_END, jump to the + label source_end. */ + +#define ONE_MORE_BYTE(c) \ + do { \ + if (src == src_stop) \ + { \ + if (src == src_end) \ + goto source_end; \ + src = source; \ + if (src == src_end) \ + goto source_end; \ + src_stop = src_end; \ + } \ + (c) = *src++; \ + } while (0) + + +#define REWIND_SRC_TO_BASE() \ + do { \ + if (src_base < source || src_base >= src_end) \ + src_stop = internal->carryover + internal->carryover_bytes; \ + src = src_base; \ + } while (0) + + +/** Push back byte C to SRC. */ + +#define UNGET_ONE_BYTE(c) \ + do { \ + if (src > source) \ + src--; \ + else \ + { \ + internal->carryover[0] = c; \ + internal->carryover_bytes = 1; \ + src = internal->carryover; \ + src_stop = src + 1; \ + } \ + } while (0); + + +/** Store multibyte representation of character C at DST and increment + DST to the next of the produced bytes. DST must be a pointer to + data area of M-text MT. If the produced bytes are going to exceed + DST_END, enlarge the data area of MT. */ + +#define EMIT_CHAR(c) \ + do { \ + int bytes = CHAR_BYTES (c); \ + int len; \ + \ + if (dst + bytes + 1 > dst_end) \ + { \ + len = dst - mt->data; \ + bytes = mt->allocated + bytes + (src_stop - src); \ + mtext__enlarge (mt, bytes); \ + dst = mt->data + len; \ + dst_end = mt->data + mt->allocated; \ + } \ + dst += CHAR_STRING (c, dst); \ + nchars++; \ + } while (0) + + +/* Check if there is enough room to produce LEN bytes at DST. If not, + go to the label insufficient_destination. */ + +#define CHECK_DST(len) \ + do { \ + if (dst + (len) > dst_end) \ + goto insufficient_destination; \ + } while (0) + + +/** Take NUM_CHARS characters (NUM_BYTES bytes) already stored at + (MT->data + MT->nbytes) into MT, and put charset property on + them with CHARSET->name. */ + +#define TAKEIN_CHARS(mt, num_chars, num_bytes, charset) \ + do { \ + int chars = (num_chars); \ + \ + if (chars > 0) \ + { \ + mtext__takein ((mt), chars, (num_bytes)); \ + if (charset) \ + mtext_put_prop ((mt), (mt)->nchars - chars, (mt)->nchars, \ + Mcharset, (void *) ((charset)->name)); \ + } \ + } while (0) + + +#define SET_SRC(mt, format, from, to) \ + do { \ + if (format <= MTEXT_FORMAT_UTF_8) \ + { \ + src = mt->data + POS_CHAR_TO_BYTE (mt, from); \ + src_end = mt->data + POS_CHAR_TO_BYTE (mt, to); \ + } \ + else if (format <= MTEXT_FORMAT_UTF_16BE) \ + { \ + src \ + = mt->data + (sizeof (short)) * POS_CHAR_TO_BYTE (mt, from); \ + src_end \ + = mt->data + (sizeof (short)) * POS_CHAR_TO_BYTE (mt, to); \ + } \ + else \ + { \ + src = mt->data + (sizeof (int)) * from; \ + src_end = mt->data + (sizeof (int)) * to; \ + } \ + } while (0) + + +#define ONE_MORE_CHAR(c, bytes, format) \ + do { \ + if (src == src_end) \ + goto finish; \ + if (format <= MTEXT_FORMAT_UTF_8) \ + c = STRING_CHAR_AND_BYTES (src, bytes); \ + else if (format <= MTEXT_FORMAT_UTF_16BE) \ + { \ + c = mtext_ref_char (mt, from++); \ + bytes = (sizeof (short)) * CHAR_UNITS_UTF16 (c); \ + } \ + else \ + { \ + c = ((unsigned *) (mt->data))[from++]; \ + bytes = sizeof (int); \ + } \ + } while (0) + + +static int +encode_unsupporeted_char (int c, unsigned char *dst, unsigned char *dst_end, + MText *mt, int pos) +{ + int len; + char *format; + + len = c < 0x10000 ? 8 : 10; + if (dst + len > dst_end) + return 0; + + mtext_put_prop (mt, pos, pos + 1, Mcoding, Mnil); + format = (c < 0xD800 ? "" + : c < 0xE000 ? "" + : c < 0x10000 ? "" + : c < 0x110000 ? "" + : ""); + sprintf ((char *) dst, format, c); + return len; +} + + + +/** Finish decoding of bytes at SOURCE (ending at SRC_END) into NCHARS + characters by CONVERTER into M-text MT. SRC is a pointer to the + not-yet processed bytes. ERROR is 1 iff an invalid byte was + found. */ + +static int +finish_decoding (MText *mt, MConverter *converter, int nchars, + const unsigned char *source, const unsigned char *src_end, + const unsigned char *src, + int error) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + + if (src == src_end) + internal->carryover_bytes = 0; + else if (error + || (converter->last_block + && ! converter->lenient)) + converter->result = MCONVERSION_RESULT_INVALID_BYTE; + else if (! converter->last_block) + { + unsigned char *dst = internal->carryover; + + if (src < source || src > src_end) + { + dst += internal->carryover_bytes; + src = source; + } + while (src < src_end) + *dst++ = *src++; + internal->carryover_bytes = dst - internal->carryover; + converter->result = MCONVERSION_RESULT_INSUFFICIENT_SRC; + } + else + { + unsigned char *dst = mt->data + mt->nbytes; + unsigned char *dst_end = mt->data + mt->allocated; + const unsigned char *src_stop = src_end; + int c; + int last_nchars = nchars; + + if (src < source || src > src_end) + src_stop = internal->carryover + internal->carryover_bytes; + while (1) + { + if (converter->at_most && nchars == converter->at_most) + break; + if (src == src_stop) + { + if (src == src_end) + break; + src = source; + if (src == src_end) + break; + src_stop = src_end; + } + c = *src++; + EMIT_CHAR (c); + } + TAKEIN_CHARS (mt, nchars - last_nchars, dst - (mt->data + mt->nbytes), + mcharset__binary); + internal->carryover_bytes = 0; + } + + converter->nchars += nchars; + converter->nbytes += ((src < source || src > src_end) ? 0 : src - source); + return (converter->result == MCONVERSION_RESULT_INVALID_BYTE ? -1 : 0); +} + + + +/* Staffs for coding-systems of type MCODING_TYPE_CHARSET. */ + +static int +setup_coding_charset (MCodingSystem *coding) +{ + int ncharsets = coding->ncharsets; + unsigned *code_charset_table; + + if (ncharsets > 1) + { + /* At first, reorder charset list by dimensions (a charset of + smaller dimension comes first). As the number of charsets is + usually very small (at most 32), we do a simple sort. */ + MCharset **charsets; + int idx = 0; + int i, j; + + MTABLE_ALLOCA (charsets, NUM_SUPPORTED_CHARSETS, MERROR_CODING); + memcpy (charsets, coding->charsets, + sizeof (MCharset *) * NUM_SUPPORTED_CHARSETS); + for (i = 0; i < 4; i++) + for (j = 0; j < ncharsets; j++) + if (charsets[j]->dimension == i) + coding->charsets[idx++] = charsets[j]; + } + + MTABLE_CALLOC (code_charset_table, 256, MERROR_CODING); + while (ncharsets--) + { + int dim = coding->charsets[ncharsets]->dimension; + int from = coding->charsets[ncharsets]->code_range[(dim - 1) * 4]; + int to = coding->charsets[ncharsets]->code_range[(dim - 1) * 4 + 1]; + + if (coding->charsets[ncharsets]->ascii_compatible) + coding->ascii_compatible = 1; + while (from <= to) + code_charset_table[from++] |= 1 << ncharsets; + } + + coding->extra_spec = (void *) code_charset_table; + return 0; +} + +static int +reset_coding_charset (MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + MCodingSystem *coding = internal->coding; + + if (! coding->ready + && setup_coding_charset (coding) < 0) + return -1; + coding->ready = 1; + return 0; +} + +static int +decode_coding_charset (const unsigned char *source, int src_bytes, MText *mt, + MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + MCodingSystem *coding = internal->coding; + const unsigned char *src = internal->carryover; + const unsigned char *src_stop = src + internal->carryover_bytes; + const unsigned char *src_end = source + src_bytes; + const unsigned char *src_base; + unsigned char *dst = mt->data + mt->nbytes; + unsigned char *dst_end = mt->data + mt->allocated; + int nchars = 0; + int last_nchars = 0; + int at_most = converter->at_most > 0 ? converter->at_most : -1; + + unsigned *code_charset_table = (unsigned *) coding->extra_spec; + MCharset **charsets = coding->charsets; + MCharset *charset = mcharset__ascii; + int error = 0; + + while (1) + { + MCharset *this_charset = NULL; + int c; + unsigned mask; + + ONE_MORE_BASE_BYTE (c); + mask = code_charset_table[c]; + if (mask) + { + int idx = 0; + unsigned code = c; + int nbytes = 1; + int dim; + + while (mask) + { + while (! (mask & 1)) mask >>= 1, idx++; + this_charset = charsets[idx]; + dim = this_charset->dimension; + while (nbytes < dim) + { + ONE_MORE_BYTE (c); + code = (code << 8) | c; + nbytes++; + } + c = DECODE_CHAR (this_charset, code); + if (c >= 0) + goto emit_char; + mask >>= 1, idx++; + } + } + + if (! converter->lenient) + break; + REWIND_SRC_TO_BASE (); + c = *src++; + this_charset = mcharset__binary; + + emit_char: + if (this_charset != mcharset__ascii + && this_charset != charset) + { + TAKEIN_CHARS (mt, nchars - last_nchars, + dst - (mt->data + mt->nbytes), charset); + charset = this_charset; + last_nchars = nchars; + } + EMIT_CHAR (c); + } + /* We reach here because of an invalid byte. */ + error = 1; + + source_end: + TAKEIN_CHARS (mt, nchars - last_nchars, + dst - (mt->data + mt->nbytes), charset); + return finish_decoding (mt, converter, nchars, + source, src_end, src_base, error); +} + +static int +encode_coding_charset (MText *mt, int from, int to, + unsigned char *destination, int dst_bytes, + MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + MCodingSystem *coding = internal->coding; + unsigned char *src, *src_end; + unsigned char *dst = destination; + unsigned char *dst_end = dst + dst_bytes; + int nchars = 0; + int ncharsets = coding->ncharsets; + MCharset **charsets = coding->charsets; + int ascii_compatible = coding->ascii_compatible; + enum MTextFormat format = mt->format; + + SET_SRC (mt, format, from, to); + while (1) + { + int c, bytes; + + ONE_MORE_CHAR (c, bytes, format); + + if (c < 0x80 && ascii_compatible) + { + CHECK_DST (1); + *dst++ = c; + } + else + { + unsigned code; + MCharset *charset = NULL; + int i = 0; + + while (1) + { + charset = charsets[i]; + code = ENCODE_CHAR (charset, c); + if (code != MCHAR_INVALID_CODE) + break; + if (++i == ncharsets) + goto unsupported_char; + } + + CHECK_DST (charset->dimension); + if (charset->dimension == 1) + { + *dst++ = code; + } + else if (charset->dimension == 2) + { + *dst++ = code >> 8; + *dst++ = code & 0xFF; + } + else if (charset->dimension == 3) + { + *dst++ = code >> 16; + *dst++ = (code >> 8) & 0xFF; + *dst++ = code & 0xFF; + } + else + { + *dst++ = code >> 24; + *dst++ = (code >> 16) & 0xFF; + *dst++ = (code >> 8) & 0xFF; + *dst++ = code & 0xFF; + } + } + src += bytes; + nchars++; + continue; + + unsupported_char: + { + int len; + + if (! converter->lenient) + break; + len = encode_unsupporeted_char (c, dst, dst_end, mt, from + nchars); + if (len == 0) + goto insufficient_destination; + dst += len; + src += bytes; + nchars++; + } + } + /* We reach here because of an unsupported char. */ + converter->result = MCONVERSION_RESULT_INVALID_CHAR; + goto finish; + + insufficient_destination: + converter->result = MCONVERSION_RESULT_INSUFFICIENT_DST; + + finish: + converter->nchars += nchars; + converter->nbytes += dst - destination; + return (converter->result == MCONVERSION_RESULT_INVALID_CHAR ? -1 : 0); +} + + +/* Staffs for coding-systems of type MCODING_TYPE_UTF (8). */ + +#define UTF8_CHARSET(p) \ + (! ((p)[0] & 0x80) ? (mcharset__unicode) \ + : CHAR_HEAD_P ((p) + 1) ? (mcharset__binary) \ + : ! ((p)[0] & 0x20) ? (mcharset__unicode) \ + : CHAR_HEAD_P ((p) + 2) ? (mcharset__binary) \ + : ! ((p)[0] & 0x10) ? (mcharset__unicode) \ + : CHAR_HEAD_P ((p) + 3) ? (mcharset__binary) \ + : ! ((p)[0] & 0x08) ? ((((((p)[0] & 0x07) << 2) \ + & (((p)[1] & 0x30) >> 4)) <= 0x10) \ + ? (mcharset__unicode) \ + : (mcharset__m17n)) \ + : CHAR_HEAD_P ((p) + 4) ? (mcharset__binary) \ + : ! ((p)[0] & 0x04) ? (mcharset__m17n) \ + : CHAR_HEAD_P ((p) + 5) ? (mcharset__binary) \ + : ! ((p)[0] & 0x02) ? (mcharset__m17n) \ + : (mcharset__binary)) + + +static int +decode_coding_utf_8 (const unsigned char *source, int src_bytes, MText *mt, + MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + MCodingSystem *coding = internal->coding; + const unsigned char *src = internal->carryover; + const unsigned char *src_stop = src + internal->carryover_bytes; + const unsigned char *src_end = source + src_bytes; + const unsigned char *src_base; + unsigned char *dst = mt->data + mt->nbytes; + unsigned char *dst_end = mt->data + mt->allocated; + int nchars = 0; + int last_nchars = 0; + int at_most = converter->at_most > 0 ? converter->at_most : -1; + int error = 0; + int full = converter->lenient || (coding->charsets[0] == mcharset__m17n); + MCharset *charset = NULL; + + while (1) + { + int c, c1, bytes; + MCharset *this_charset = NULL; + + ONE_MORE_BASE_BYTE (c); + + if (!(c & 0x80)) + bytes = 1; + else if (!(c & 0x40)) + goto invalid_byte; + else if (!(c & 0x20)) + bytes = 2, c &= 0x1F; + else if (!(c & 0x10)) + bytes = 3, c &= 0x0F; + else if (!(c & 0x08)) + bytes = 4, c &= 0x07; + else if (!(c & 0x04)) + bytes = 5, c &= 0x03; + else if (!(c & 0x02)) + bytes = 6, c &= 0x01; + else + goto invalid_byte; + + while (bytes-- > 1) + { + ONE_MORE_BYTE (c1); + if ((c1 & 0xC0) != 0x80) + goto invalid_byte; + c = (c << 6) | (c1 & 0x3F); + } + + if (full + || c < 0xD800 || (c >= 0xE000 && c < 0x110000)) + goto emit_char; + + invalid_byte: + if (! converter->lenient) + break; + REWIND_SRC_TO_BASE (); + c = *src++; + this_charset = mcharset__binary; + + emit_char: + if (this_charset != charset) + { + TAKEIN_CHARS (mt, nchars - last_nchars, + dst - (mt->data + mt->nbytes), charset); + charset = this_charset; + last_nchars = nchars; + } + EMIT_CHAR (c); + } + /* We reach here because of an invalid byte. */ + error = 1; + + source_end: + TAKEIN_CHARS (mt, nchars - last_nchars, + dst - (mt->data + mt->nbytes), charset); + return finish_decoding (mt, converter, nchars, + source, src_end, src_base, error); +} + +static int +encode_coding_utf_8 (MText *mt, int from, int to, + unsigned char *destination, int dst_bytes, + MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + MCodingSystem *coding = internal->coding; + unsigned char *src, *src_end; + unsigned char *dst = destination; + unsigned char *dst_end = dst + dst_bytes; + int nchars = 0; + enum MTextFormat format = mt->format; + + SET_SRC (mt, format, from, to); + + if (format <= MTEXT_FORMAT_UTF_8 + && (converter->lenient + || coding->charsets[0] == mcharset__m17n)) + { + if (dst_bytes < src_end - src) + { + int byte_pos = (src + dst_bytes) - mt->data; + + to = POS_BYTE_TO_CHAR (mt, byte_pos); + byte_pos = POS_CHAR_TO_BYTE (mt, to); + src_end = mt->data + byte_pos; + converter->result = MCONVERSION_RESULT_INSUFFICIENT_DST; + } + memcpy (destination, src, src_end - src); + nchars = to - from; + dst += src_end - src; + goto finish; + } + + while (1) + { + int c, bytes; + + ONE_MORE_CHAR (c, bytes, format); + + if ((c >= 0xD800 && c < 0xE000) || c >= 0x110000) + break; + CHECK_DST (bytes); + dst += CHAR_STRING (c, dst); + src += bytes; + nchars++; + } + /* We reach here because of an unsupported char. */ + converter->result = MCONVERSION_RESULT_INVALID_CHAR; + goto finish; + + insufficient_destination: + converter->result = MCONVERSION_RESULT_INSUFFICIENT_DST; + + finish: + converter->nchars += nchars; + converter->nbytes += dst - destination; + return (converter->result == MCONVERSION_RESULT_INVALID_CHAR ? -1 : 0); +} + + +/* Staffs for coding-systems of type MCODING_TYPE_UTF (16 & 32). */ + +enum utf_bom + { + UTF_BOM_MAYBE, + UTF_BOM_NO, + UTF_BOM_YES, + UTF_BOM_MAX + }; + +enum utf_endian + { + UTF_BIG_ENDIAN, + UTF_LITTLE_ENDIAN, + UTF_ENDIAN_MAX + }; + +struct utf_status +{ + int surrogate; + enum utf_bom bom; + enum utf_endian endian; +}; + +static int +setup_coding_utf (MCodingSystem *coding) +{ + MCodingInfoUTF *info = (MCodingInfoUTF *) (coding->extra_info); + MCodingInfoUTF *spec; + + if (info->code_unit_bits == 8) + coding->ascii_compatible = 1; + else if (info->code_unit_bits == 16 + || info->code_unit_bits == 32) + { + if (info->bom < 0 || info->bom > 2 + || info->endian < 0 || info->endian > 1) + MERROR (MERROR_CODING, -1); + } + else + return -1; + + MSTRUCT_CALLOC (spec, MERROR_CODING); + *spec = *info; + coding->extra_spec = (void *) (spec); + return 0; +} + +static int +reset_coding_utf (MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + MCodingSystem *coding = internal->coding; + struct utf_status *status = (struct utf_status *) &(converter->status); + + if (! coding->ready + && setup_coding_utf (coding) < 0) + return -1; + coding->ready = 1; + + status->surrogate = 0; + status->bom = ((MCodingInfoUTF *) (coding->extra_spec))->bom; + status->endian = ((MCodingInfoUTF *) (coding->extra_spec))->endian; + return 0; +} + +static int +decode_coding_utf_16 (const unsigned char *source, int src_bytes, MText *mt, + MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + const unsigned char *src = internal->carryover; + const unsigned char *src_stop = src + internal->carryover_bytes; + const unsigned char *src_end = source + src_bytes; + const unsigned char *src_base; + unsigned char *dst = mt->data + mt->nbytes; + unsigned char *dst_end = mt->data + mt->allocated; + int nchars = 0; + int last_nchars = 0; + int at_most = converter->at_most > 0 ? converter->at_most : -1; + struct utf_status *status = (struct utf_status *) &(converter->status); + unsigned char b1, b2; + MCharset *charset = NULL; + int error = 0; + + if (status->bom != UTF_BOM_NO) + { + int c; + + ONE_MORE_BASE_BYTE (b1); + ONE_MORE_BYTE (b2); + c = (b1 << 8) | b2; + if (c == 0xFEFF) + status->endian = UTF_BIG_ENDIAN; + else if (c == 0xFFFE) + status->endian = UTF_LITTLE_ENDIAN; + else if (status->bom == UTF_BOM_MAYBE + || converter->lenient) + { + status->endian = UTF_BIG_ENDIAN; + REWIND_SRC_TO_BASE (); + } + else + { + error = 1; + goto source_end; + } + status->bom = UTF_BOM_NO; + } + + while (1) + { + int c, c1; + MCharset *this_charset = NULL; + + ONE_MORE_BASE_BYTE (b1); + ONE_MORE_BYTE (b2); + if (status->endian == UTF_BIG_ENDIAN) + c = ((b1 << 8) | b2); + else + c = ((b2 << 8) | b1); + if (c < 0xD800 || c >= 0xE000) + goto emit_char; + else if (c < 0xDC00) + { + ONE_MORE_BYTE (b1); + ONE_MORE_BYTE (b2); + if (status->endian == UTF_BIG_ENDIAN) + c1 = ((b1 << 8) | b2); + else + c1 = ((b2 << 8) | b1); + if (c1 < 0xDC00 || c1 >= 0xE000) + goto invalid_byte; + c = 0x10000 + ((c - 0xD800) << 10) + (c1 - 0xDC00); + goto emit_char; + } + + invalid_byte: + if (! converter->lenient) + break; + REWIND_SRC_TO_BASE (); + ONE_MORE_BYTE (b1); + ONE_MORE_BYTE (b2); + if (status->endian == UTF_BIG_ENDIAN) + c = ((b1 << 8) | b2); + else + c = ((b2 << 8) | b1); + this_charset = mcharset__binary; + + emit_char: + if (this_charset != charset) + { + TAKEIN_CHARS (mt, nchars - last_nchars, + dst - (mt->data + mt->nbytes), charset); + charset = this_charset; + last_nchars = nchars; + } + EMIT_CHAR (c); + } + /* We reach here because of an invalid byte. */ + error = 1; + + source_end: + TAKEIN_CHARS (mt, nchars - last_nchars, + dst - (mt->data + mt->nbytes), charset); + return finish_decoding (mt, converter, nchars, + source, src_end, src_base, error); +} + + +static int +decode_coding_utf_32 (const unsigned char *source, int src_bytes, MText *mt, + MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + const unsigned char *src = internal->carryover; + const unsigned char *src_stop = src + internal->carryover_bytes; + const unsigned char *src_end = source + src_bytes; + const unsigned char *src_base; + unsigned char *dst = mt->data + mt->nbytes; + unsigned char *dst_end = mt->data + mt->allocated; + int nchars = 0; + int last_nchars = 0; + int at_most = converter->at_most > 0 ? converter->at_most : -1; + struct utf_status *status = (struct utf_status *) &(converter->status); + unsigned char b1, b2, b3, b4; + MCharset *charset = NULL; + int error = 0; + + if (status->bom != UTF_BOM_NO) + { + unsigned c; + + ONE_MORE_BASE_BYTE (b1); + ONE_MORE_BYTE (b2); + ONE_MORE_BYTE (b3); + ONE_MORE_BYTE (b4); + c = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4; + if (c == 0x0000FEFF) + status->endian = UTF_BIG_ENDIAN; + else if (c == 0xFFFE0000) + status->endian = UTF_LITTLE_ENDIAN; + else if (status->bom == UTF_BOM_MAYBE + || converter->lenient) + { + status->endian = UTF_BIG_ENDIAN; + REWIND_SRC_TO_BASE (); + } + else + { + error = 1; + goto source_end; + } + status->bom = UTF_BOM_NO; + } + + while (1) + { + unsigned c; + MCharset *this_charset = NULL; + + ONE_MORE_BASE_BYTE (b1); + ONE_MORE_BYTE (b2); + ONE_MORE_BYTE (b3); + ONE_MORE_BYTE (b4); + if (status->endian == UTF_BIG_ENDIAN) + c = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4; + else + c = (b4 << 24) | (b3 << 16) | (b2 << 8) | b1; + if (c < 0xD800 || (c >= 0xE000 && c < 0x110000)) + goto emit_char; + + if (! converter->lenient) + break; + REWIND_SRC_TO_BASE (); + ONE_MORE_BYTE (c); + this_charset = mcharset__binary; + + emit_char: + if (this_charset != charset) + { + TAKEIN_CHARS (mt, nchars - last_nchars, + dst - (mt->data + mt->nbytes), charset); + charset = this_charset; + last_nchars = nchars; + } + EMIT_CHAR (c); + } + /* We reach here because of an invalid byte. */ + error = 1; + + source_end: + TAKEIN_CHARS (mt, nchars - last_nchars, + dst - (mt->data + mt->nbytes), charset); + return finish_decoding (mt, converter, nchars, + source, src_end, src_base, error); +} + + +static int +encode_coding_utf_16 (MText *mt, int from, int to, + unsigned char *destination, int dst_bytes, + MConverter *converter) +{ + unsigned char *src, *src_end; + unsigned char *dst = destination; + unsigned char *dst_end = dst + dst_bytes; + int nchars = 0; + struct utf_status *status = (struct utf_status *) &(converter->status); + int big_endian = status->endian == UTF_BIG_ENDIAN; + enum MTextFormat format = mt->format; + + SET_SRC (mt, format, from, to); + + if (status->bom != UTF_BOM_NO) + { + CHECK_DST (2); + if (big_endian) + *dst++ = 0xFE, *dst++ = 0xFF; + else + *dst++ = 0xFF, *dst++ = 0xFE; + status->bom = UTF_BOM_NO; + } + + while (1) + { + int c, bytes; + + ONE_MORE_CHAR (c, bytes, format); + + if (c < 0xD800 || (c >= 0xE000 && c < 0x10000)) + { + CHECK_DST (2); + if (big_endian) + *dst++ = c >> 8, *dst++ = c & 0xFF; + else + *dst++ = c & 0xFF, *dst++ = c >> 8; + } + else if (c >= 0x10000 && c < 0x110000) + { + int c1, c2; + + CHECK_DST (4); + c -= 0x10000; + c1 = (c >> 10) + 0xD800; + c2 = (c & 0x3FF) + 0xDC00; + if (big_endian) + *dst++ = c1 >> 8, *dst++ = c1 & 0xFF, + *dst++ = c2 >> 8, *dst++ = c2 & 0xFF; + else + *dst++ = c1 & 0xFF, *dst++ = c1 >> 8, + *dst++ = c2 & 0xFF, *dst++ = c2 >> 8; + } + else + { + unsigned char buf[11]; + int len, i; + + if (! converter->lenient) + break; + len = encode_unsupporeted_char (c, buf, buf + (dst_end - dst), + mt, from + nchars); + if (len == 0) + goto insufficient_destination; + if (big_endian) + for (i = 0; i < len; i++) + *dst++ = 0, *dst++ = buf[i]; + else + for (i = 0; i < len; i++) + *dst++ = buf[i], *dst++ = 0; + } + src += bytes; + nchars++; + } + /* We reach here because of an unsupported char. */ + converter->result = MCONVERSION_RESULT_INVALID_CHAR; + goto finish; + + insufficient_destination: + converter->result = MCONVERSION_RESULT_INSUFFICIENT_DST; + + finish: + converter->nchars += nchars; + converter->nbytes += dst - destination; + return (converter->result == MCONVERSION_RESULT_INVALID_CHAR ? -1 : 0); +} + +static int +encode_coding_utf_32 (MText *mt, int from, int to, + unsigned char *destination, int dst_bytes, + MConverter *converter) +{ + unsigned char *src, *src_end; + unsigned char *dst = destination; + unsigned char *dst_end = dst + dst_bytes; + int nchars = 0; + struct utf_status *status = (struct utf_status *) &(converter->status); + int big_endian = status->endian == UTF_BIG_ENDIAN; + enum MTextFormat format = mt->format; + + SET_SRC (mt, format, from, to); + + if (status->bom != UTF_BOM_NO) + { + CHECK_DST (4); + if (big_endian) + *dst++ = 0x00, *dst++ = 0x00, *dst++ = 0xFE, *dst++ = 0xFF; + else + *dst++ = 0xFF, *dst++ = 0xFE, *dst++ = 0x00, *dst++ = 0x00; + status->bom = UTF_BOM_NO; + } + + while (1) + { + int c, bytes; + + ONE_MORE_CHAR (c, bytes, format); + + if (c < 0xD800 || (c >= 0xE000 && c < 0x110000)) + { + CHECK_DST (4); + if (big_endian) + *dst++ = 0x00, *dst++ = c >> 16, + *dst++ = (c >> 8) & 0xFF, *dst++ = c & 0xFF; + else + *dst++ = c & 0xFF, *dst++ = (c >> 8) & 0xFF, + *dst++ = c >> 16, *dst++ = 0x00; + } + else + { + unsigned char buf[11]; + int len, i; + + if (! converter->lenient) + break; + len = encode_unsupporeted_char (c, buf, buf + (dst_end - dst), + mt, from + nchars); + if (len == 0) + goto insufficient_destination; + if (big_endian) + for (i = 0; i < len; i++) + *dst++ = 0, *dst++ = buf[i]; + else + for (i = 0; i < len; i++) + *dst++ = buf[i], *dst++ = 0; + } + src += bytes; + nchars++; + } + /* We reach here because of an unsupported char. */ + converter->result = MCONVERSION_RESULT_INVALID_CHAR; + goto finish; + + insufficient_destination: + converter->result = MCONVERSION_RESULT_INSUFFICIENT_DST; + + finish: + converter->nchars += nchars; + converter->nbytes += dst - destination; + return (converter->result == MCONVERSION_RESULT_INVALID_CHAR ? -1 : 0); +} + + +/* Staffs for coding-systems of type MCODING_TYPE_ISO_2022. */ + +#define ISO_CODE_STX 0x02 /* start text */ +#define ISO_CODE_SO 0x0E /* shift-out */ +#define ISO_CODE_SI 0x0F /* shift-in */ +#define ISO_CODE_SS2_7 0x19 /* single-shift-2 for 7-bit code */ +#define ISO_CODE_ESC 0x1B /* escape */ +#define ISO_CODE_SS2 0x8E /* single-shift-2 */ +#define ISO_CODE_SS3 0x8F /* single-shift-3 */ + +/** Structure pointed by MCodingSystem.extra_spec. */ + +struct iso_2022_spec +{ + unsigned flags; + + /** Initial graphic registers (0..3) invoked to each graphic + plane left and right. */ + int initial_invocation[2]; + + /** Initially designated charsets for each graphic register. */ + MCharset *initial_designation[4]; + + int n_designations; + char *designations; + + int use_esc; +}; + +struct iso_2022_status +{ + int invocation[2]; + MCharset *designation[4]; + unsigned single_shifting : 1; + unsigned bol : 1; + unsigned r2l : 1; + unsigned utf8_shifting : 1; + MCharset *non_standard_charset; + int non_standard_charset_bytes; + int non_standard_encoding; +}; + +enum iso_2022_code_class { + ISO_control_0, /* Control codes in the range + 0x00..0x1F and 0x7F, except for the + following 4 codes. */ + ISO_shift_out, /* ISO_CODE_SO (0x0E) */ + ISO_shift_in, /* ISO_CODE_SI (0x0F) */ + ISO_single_shift_2_7, /* ISO_CODE_SS2_7 (0x19) */ + ISO_escape, /* ISO_CODE_SO (0x1B) */ + ISO_control_1, /* Control codes in the range + 0x80..0x9F, except for the + following 3 codes. */ + ISO_single_shift_2, /* ISO_CODE_SS2 (0x8E) */ + ISO_single_shift_3, /* ISO_CODE_SS3 (0x8F) */ + ISO_control_sequence_introducer, /* ISO_CODE_CSI (0x9B) */ + ISO_0x20_or_0x7F, /* Codes of the values 0x20 or 0x7F. */ + ISO_graphic_plane_0, /* Graphic codes in the range 0x21..0x7E. */ + ISO_0xA0_or_0xFF, /* Codes of the values 0xA0 or 0xFF. */ + ISO_graphic_plane_1 /* Graphic codes in the range 0xA1..0xFE. */ +} iso_2022_code_class[256]; + + +#define MCODING_ISO_DESIGNATION_MASK \ + (MCODING_ISO_DESIGNATION_G0 \ + | MCODING_ISO_DESIGNATION_G1 \ + | MCODING_ISO_DESIGNATION_CTEXT \ + | MCODING_ISO_DESIGNATION_CTEXT_EXT) + +static int +setup_coding_iso_2022 (MCodingSystem *coding) +{ + MCodingInfoISO2022 *info = (MCodingInfoISO2022 *) (coding->extra_info); + int ncharsets = coding->ncharsets; + struct iso_2022_spec *spec; + int designation_policy = info->flags & MCODING_ISO_DESIGNATION_MASK; + int i; + + coding->ascii_compatible = 0; + + MSTRUCT_CALLOC (spec, MERROR_CODING); + + spec->flags = info->flags; + spec->initial_invocation[0] = info->initial_invocation[0]; + spec->initial_invocation[1] = info->initial_invocation[1]; + for (i = 0; i < 4; i++) + spec->initial_designation[i] = NULL; + if (designation_policy) + { + spec->n_designations = ncharsets; + if (spec->flags & MCODING_ISO_FULL_SUPPORT) + spec->n_designations += mcharset__iso_2022_table.used; + MTABLE_CALLOC (spec->designations, spec->n_designations, MERROR_CODING); + for (i = 0; i < spec->n_designations; i++) + spec->designations[i] = -1; + } + else + { + if (spec->flags & MCODING_ISO_FULL_SUPPORT) + MERROR (MERROR_CODING, -1); + spec->designations = NULL; + } + + for (i = 0; i < ncharsets; i++) + { + int reg = info->designations[i]; + + if (reg != -5 + && coding->charsets[i]->final_byte > 0 + && (reg < -4 || reg > 3)) + MERROR (MERROR_CODING, -1); + if (reg >= 0) + { + if (spec->initial_designation[reg]) + MERROR (MERROR_CODING, -1); + spec->initial_designation[reg] = coding->charsets[i]; + } + else if (reg >= -4) + { + if (! designation_policy + && ! (spec->flags & MCODING_ISO_EUC_TW_SHIFT)) + MERROR (MERROR_CODING, -1); + reg += 4; + } + + if (designation_policy) + spec->designations[i] = reg; + if (coding->charsets[i] == mcharset__ascii) + coding->ascii_compatible = 1; + } + + if (coding->ascii_compatible + && (spec->flags & (MCODING_ISO_DESIGNATION_G0 + | MCODING_ISO_DESIGNATION_CTEXT + | MCODING_ISO_DESIGNATION_CTEXT_EXT + | MCODING_ISO_LOCKING_SHIFT))) + coding->ascii_compatible = 0; + + if (spec->flags & MCODING_ISO_FULL_SUPPORT) + for (i = 0; i < mcharset__iso_2022_table.used; i++) + { + MCharset *charset = mcharset__iso_2022_table.charsets[i]; + + spec->designations[ncharsets + i] + = ((designation_policy == MCODING_ISO_DESIGNATION_CTEXT + || designation_policy == MCODING_ISO_DESIGNATION_CTEXT_EXT) + ? (charset->code_range[0] == 32 + || charset->code_range[1] == 255) + : designation_policy == MCODING_ISO_DESIGNATION_G1); + } + + spec->use_esc = ((spec->flags & MCODING_ISO_DESIGNATION_MASK) + || ((spec->flags & MCODING_ISO_LOCKING_SHIFT) + && (spec->initial_designation[2] + || spec->initial_designation[3])) + || (! (spec->flags & MCODING_ISO_EIGHT_BIT) + && (spec->flags & MCODING_ISO_SINGLE_SHIFT)) + || (spec->flags & MCODING_ISO_ISO6429)); + + coding->extra_spec = (void *) spec; + + return 0; +} + +static int +reset_coding_iso_2022 (MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + MCodingSystem *coding = internal->coding; + struct iso_2022_status *status + = (struct iso_2022_status *) &(converter->status); + struct iso_2022_spec *spec; + int i; + + if (! coding->ready + && setup_coding_iso_2022 (coding) < 0) + return -1; + coding->ready = 1; + + spec = (struct iso_2022_spec *) coding->extra_spec; + status->invocation[0] = spec->initial_invocation[0]; + status->invocation[1] = spec->initial_invocation[1]; + for (i = 0; i < 4; i++) + status->designation[i] = spec->initial_designation[i]; + status->single_shifting = 0; + status->bol = 1; + status->r2l = 0; + + return 0; +} + +#define ISO2022_DECODE_DESIGNATION(reg, dim, chars, final, rev) \ + do { \ + MCharset *charset; \ + \ + if ((final) < '0' || (final) >= 128) \ + goto invalid_byte; \ + if (rev < 0) \ + { \ + charset = MCHARSET_ISO_2022 ((dim), (chars), (final)); \ + if (! (spec->flags & MCODING_ISO_FULL_SUPPORT)) \ + { \ + int i; \ + \ + for (i = 0; i < coding->ncharsets; i++) \ + if (charset == coding->charsets[i]) \ + break; \ + if (i == coding->ncharsets) \ + goto invalid_byte; \ + } \ + } \ + else \ + { \ + int i; \ + \ + for (i = 0; i < mcharset__iso_2022_table.used; i++) \ + { \ + charset = mcharset__iso_2022_table.charsets[i]; \ + if (charset->revision == (rev) \ + && charset->dimension == (dim) \ + && charset->final_byte == (final) \ + && (charset->code_range[1] == (chars) \ + || ((chars) == 96 && charset->code_range[1] == 255))) \ + break; \ + } \ + if (i == mcharset__iso_2022_table.used) \ + goto invalid_byte; \ + } \ + status->designation[reg] = charset; \ + } while (0) + + +static MCharset * +find_ctext_non_standard_charset (char *charset_name) +{ + MCharset *charset; + + if (! strcmp (charset_name, "koi8-r")) + charset = MCHARSET (msymbol ("koi8-r")); + else if (! strcmp (charset_name, "big5-0")) + charset = MCHARSET (msymbol ("big5")); + else + charset = NULL; + return charset; +} + +static int +decode_coding_iso_2022 (const unsigned char *source, int src_bytes, MText *mt, + MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + MCodingSystem *coding = internal->coding; + const unsigned char *src = internal->carryover; + const unsigned char *src_stop = src + internal->carryover_bytes; + const unsigned char *src_end = source + src_bytes; + const unsigned char *src_base; + unsigned char *dst = mt->data + mt->nbytes; + unsigned char *dst_end = mt->data + mt->allocated; + int nchars = 0; + int last_nchars = 0; + int at_most = converter->at_most > 0 ? converter->at_most : -1; + struct iso_2022_spec *spec = (struct iso_2022_spec *) coding->extra_spec; + struct iso_2022_status *status + = (struct iso_2022_status *) &(converter->status); + MCharset *charset0, *charset1, *charset; + int error = 0; + MCharset *cns_charsets[15]; + + charset0 = (status->invocation[0] >= 0 + ? status->designation[status->invocation[0]] : NULL); + charset1 = (status->invocation[1] >= 0 + ? status->designation[status->invocation[1]] : NULL); + charset = mcharset__ascii; + + if (spec->flags & MCODING_ISO_EUC_TW_SHIFT) + { + int i; + + memset (cns_charsets, 0, sizeof (cns_charsets)); + for (i = 0; i < coding->ncharsets; i++) + if (coding->charsets[i]->dimension == 2 + && coding->charsets[i]->code_range[1] == 126) + { + int final = coding->charsets[i]->final_byte; + + if (final >= 'G' && final <= 'M') + cns_charsets[final - 'G'] = coding->charsets[i]; + else if (final < 0) + cns_charsets[14] = coding->charsets[i]; + } + } + + while (1) + { + MCharset *this_charset = NULL; + int c1, c2, c3; + + ONE_MORE_BASE_BYTE (c1); + + if (status->utf8_shifting) + { + int buf[6]; + int bytes = CHAR_BYTES_BY_HEAD (c1); + int i; + + buf[0] = c1; + for (i = 1; i < bytes; i++) + { + ONE_MORE_BYTE (c1); + buf[i] = c1; + } + this_charset = UTF8_CHARSET (buf); + c1 = STRING_CHAR_UTF8 (buf); + goto emit_char; + } + + if (status->non_standard_encoding > 0) + { + int i; + + this_charset = status->non_standard_charset; + for (i = 1; i < status->non_standard_charset_bytes; i++) + { + ONE_MORE_BYTE (c2); + c1 = (c1 << 8) | c2; + } + c1 = DECODE_CHAR (this_charset, c1); + goto emit_char; + } + + switch (iso_2022_code_class[c1]) + { + case ISO_graphic_plane_0: + this_charset = charset0; + break; + + case ISO_0x20_or_0x7F: + if (! charset0 + || (charset0->code_range[0] != 32 + && charset0->code_range[1] != 255)) + /* This is SPACE or DEL. */ + this_charset = mcharset__ascii; + else + /* This is a graphic character of plane 0. */ + this_charset = charset0; + break; + + case ISO_graphic_plane_1: + if (!charset1) + goto invalid_byte; + this_charset = charset1; + break; + + case ISO_0xA0_or_0xFF: + if (! charset1 + || charset1->code_range[0] == 33 + || ! (spec->flags & MCODING_ISO_EIGHT_BIT)) + goto invalid_byte; + /* This is a graphic character of plane 1. */ + if (! charset1) + goto invalid_byte; + this_charset = charset1; + break; + + case ISO_control_0: + this_charset = mcharset__ascii; + break; + + case ISO_control_1: + goto invalid_byte; + + case ISO_shift_out: + if ((spec->flags & MCODING_ISO_LOCKING_SHIFT) + && status->designation[1]) + { + status->invocation[0] = 1; + charset0 = status->designation[1]; + continue; + } + this_charset = mcharset__ascii; + break; + + case ISO_shift_in: + if (spec->flags & MCODING_ISO_LOCKING_SHIFT) + { + status->invocation[0] = 0; + charset0 = status->designation[0]; + continue; + } + this_charset = mcharset__ascii; + break; + + case ISO_single_shift_2_7: + if (! (spec->flags & MCODING_ISO_SINGLE_SHIFT_7)) + { + this_charset = mcharset__ascii; + break; + } + c1 = 'N'; + goto label_escape_sequence; + + case ISO_single_shift_2: + if (spec->flags & MCODING_ISO_EUC_TW_SHIFT) + { + ONE_MORE_BYTE (c1); + if (c1 < 0xA1 || (c1 > 0xA7 && c1 < 0xAF) || c1 > 0xAF + || ! cns_charsets[c1 - 0xA1]) + goto invalid_byte; + status->designation[2] = cns_charsets[c1 - 0xA1]; + } + else if (! (spec->flags & MCODING_ISO_SINGLE_SHIFT)) + goto invalid_byte; + /* SS2 is handled as an escape sequence of ESC 'N' */ + c1 = 'N'; + goto label_escape_sequence; + + case ISO_single_shift_3: + if (! (spec->flags & MCODING_ISO_SINGLE_SHIFT)) + goto invalid_byte; + /* SS2 is handled as an escape sequence of ESC 'O' */ + c1 = 'O'; + goto label_escape_sequence; + + case ISO_control_sequence_introducer: + /* CSI is handled as an escape sequence of ESC '[' ... */ + c1 = '['; + goto label_escape_sequence; + + case ISO_escape: + if (! spec->use_esc) + { + this_charset = mcharset__ascii; + break; + } + ONE_MORE_BYTE (c1); + label_escape_sequence: + /* Escape sequences handled here are invocation, + designation, and direction specification. */ + switch (c1) + { + case '&': /* revision of following character set */ + if (! (spec->flags & MCODING_ISO_DESIGNATION_MASK)) + goto unused_escape_sequence; + ONE_MORE_BYTE (c1); + if (c1 < '@' || c1 > '~') + goto invalid_byte; + ONE_MORE_BYTE (c1); + if (c1 != ISO_CODE_ESC) + goto invalid_byte; + ONE_MORE_BYTE (c1); + goto label_escape_sequence; + + case '$': /* designation of 2-byte character set */ + if (! (spec->flags & MCODING_ISO_DESIGNATION_MASK)) + goto unused_escape_sequence; + ONE_MORE_BYTE (c1); + if (c1 >= '@' && c1 <= 'B') + { /* designation of JISX0208.1978, GB2312.1980, or + JISX0208.1980 */ + ISO2022_DECODE_DESIGNATION (0, 2, 94, c1, -1); + } + else if (c1 >= 0x28 && c1 <= 0x2B) + { /* designation of (dimension 2, chars 94) character set */ + ONE_MORE_BYTE (c2); + ISO2022_DECODE_DESIGNATION (c1 - 0x28, 2, 94, c2, -1); + } + else if (c1 >= 0x2C && c1 <= 0x2F) + { /* designation of (dimension 2, chars 96) character set */ + ONE_MORE_BYTE (c2); + ISO2022_DECODE_DESIGNATION (c1 - 0x2C, 2, 96, c2, -1); + } + else + goto invalid_byte; + /* We must update these variables now. */ + if (status->invocation[0] >= 0) + charset0 = status->designation[status->invocation[0]]; + if (status->invocation[1] >= 0) + charset1 = status->designation[status->invocation[1]]; + continue; + + case 'n': /* invocation of locking-shift-2 */ + if (! (spec->flags & MCODING_ISO_LOCKING_SHIFT) + || ! status->designation[2]) + goto invalid_byte; + status->invocation[0] = 2; + charset0 = status->designation[2]; + continue; + + case 'o': /* invocation of locking-shift-3 */ + if (! (spec->flags & MCODING_ISO_LOCKING_SHIFT) + || ! status->designation[3]) + goto invalid_byte; + status->invocation[0] = 3; + charset0 = status->designation[3]; + continue; + + case 'N': /* invocation of single-shift-2 */ + if (! ((spec->flags & MCODING_ISO_SINGLE_SHIFT) + || (spec->flags & MCODING_ISO_EUC_TW_SHIFT)) + || ! status->designation[2]) + goto invalid_byte; + this_charset = status->designation[2]; + ONE_MORE_BYTE (c1); + if (c1 < 0x20 || (c1 >= 0x80 && c1 < 0xA0)) + goto invalid_byte; + break; + + case 'O': /* invocation of single-shift-3 */ + if (! (spec->flags & MCODING_ISO_SINGLE_SHIFT) + || ! status->designation[3]) + goto invalid_byte; + this_charset = status->designation[3]; + ONE_MORE_BYTE (c1); + if (c1 < 0x20 || (c1 >= 0x80 && c1 < 0xA0)) + goto invalid_byte; + break; + + case '[': /* specification of direction */ + if (! (spec->flags & MCODING_ISO_ISO6429)) + goto invalid_byte; + /* For the moment, nested direction is not supported. + So, (coding->mode & CODING_MODE_DIRECTION) zero means + left-to-right, and nonzero means right-to-left. */ + ONE_MORE_BYTE (c1); + switch (c1) + { + case ']': /* end of the current direction */ + case '0': /* end of the current direction */ + status->r2l = 0; + break; + + case '1': /* start of left-to-right direction */ + ONE_MORE_BYTE (c1); + if (c1 != ']') + goto invalid_byte; + status->r2l = 0; + break; + + case '2': /* start of right-to-left direction */ + ONE_MORE_BYTE (c1); + if (c1 != ']') + goto invalid_byte; + status->r2l = 1; + break; + + default: + goto invalid_byte; + } + continue; + + case '%': + { + char charset_name[16]; + int bytes; + int i; + + if (! (spec->flags & MCODING_ISO_DESIGNATION_CTEXT_EXT)) + goto invalid_byte; + /* Compound-text uses these escape sequences: + + ESC % G -- utf-8 bytes -- ESC % @ + ESC % / 1 M L -- charset name -- STX -- bytes -- + ESC % / 2 M L -- charset name -- STX -- bytes -- + ESC % / 3 M L -- charset name -- STX -- bytes -- + ESC % / 4 M L -- charset name -- STX -- bytes -- + + It also uses this sequence but that is not yet + supported here. + + ESC % / 0 M L -- charset name -- STX -- bytes -- */ + + ONE_MORE_BYTE (c1); + if (c1 == 'G') + { + status->utf8_shifting = 1; + continue; + } + if (c1 == '@') + { + if (! status->utf8_shifting) + goto invalid_byte; + status->utf8_shifting = 0; + continue; + } + if (c1 != '/') + goto invalid_byte; + ONE_MORE_BYTE (c1); + if (c1 < '1' || c1 > '4') + goto invalid_byte; + status->non_standard_charset_bytes = c1 - '0'; + ONE_MORE_BYTE (c1); + ONE_MORE_BYTE (c2); + if (c1 < 128 || c2 < 128) + goto invalid_byte; + bytes = (c1 - 128) * 128 + (c2 - 128); + for (i = 0; i < 16; i++) + { + ONE_MORE_BYTE (c1); + if (c1 == ISO_CODE_STX) + break; + charset_name[i] = TOLOWER (c1); + } + if (i == 16) + goto invalid_byte; + charset_name[i++] = '\0'; + this_charset = find_ctext_non_standard_charset (charset_name); + if (! this_charset) + goto invalid_byte; + status->non_standard_charset = this_charset; + status->non_standard_encoding = bytes - i; + continue; + } + + default: + if (! (spec->flags & MCODING_ISO_DESIGNATION_MASK)) + goto unused_escape_sequence; + if (c1 >= 0x28 && c1 <= 0x2B) + { /* designation of (dimension 1, chars 94) charset */ + ONE_MORE_BYTE (c2); + ISO2022_DECODE_DESIGNATION (c1 - 0x28, 1, 94, c2, -1); + } + else if (c1 >= 0x2C && c1 <= 0x2F) + { /* designation of (dimension 1, chars 96) charset */ + ONE_MORE_BYTE (c2); + ISO2022_DECODE_DESIGNATION (c1 - 0x2C, 1, 96, c2, -1); + } + else + goto invalid_byte; + /* We must update these variables now. */ + if (status->invocation[0] >= 0) + charset0 = status->designation[status->invocation[0]]; + if (status->invocation[1] >= 0) + charset1 = status->designation[status->invocation[1]]; + continue; + + unused_escape_sequence: + UNGET_ONE_BYTE (c1); + c1 = ISO_CODE_ESC; + this_charset = mcharset__ascii; + } + } + + if (this_charset->dimension == 1) + { + if (this_charset->code_range[1] <= 128) + c1 &= 0x7F; + } + else if (this_charset->dimension == 2) + { + ONE_MORE_BYTE (c2); + c1 = ((c1 & 0x7F) << 8) | (c2 & 0x7F); + } + else /* i.e. (dimension == 3) */ + { + ONE_MORE_BYTE (c2); + ONE_MORE_BYTE (c3); + c1 = ((c1 & 0x7F) << 16) | ((c2 & 0x7F) << 8) | (c3 & 0x7F); + } + c1 = DECODE_CHAR (this_charset, c1); + goto emit_char; + + invalid_byte: + if (! converter->lenient) + break; + REWIND_SRC_TO_BASE (); + c1 = *src++; + this_charset = mcharset__binary; + + emit_char: + if (this_charset != mcharset__ascii + && this_charset != charset) + { + TAKEIN_CHARS (mt, nchars - last_nchars, + dst - (mt->data + mt->nbytes), charset); + charset = this_charset; + last_nchars = nchars; + } + EMIT_CHAR (c1); + if (status->non_standard_encoding > 0) + status->non_standard_encoding -= status->non_standard_charset_bytes; + } + /* We reach here because of an invalid byte. */ + error = 1; + + + + source_end: + TAKEIN_CHARS (mt, nchars - last_nchars, + dst - (mt->data + mt->nbytes), charset); + return finish_decoding (mt, converter, nchars, + source, src_end, src_base, error); + +} + +/* Produce codes (escape sequence) for designating CHARSET to graphic + register REG at DST, and increment DST. If CHARSET->final-char is + '@', 'A', or 'B' and SHORT_FORM is nonzero, produce designation + sequence of short-form. Update STATUS->designation. */ + +#define ISO2022_ENCODE_DESIGNATION(reg, charset, spec, status) \ + do { \ + char *intermediate_char_94 = "()*+"; \ + char *intermediate_char_96 = ",-./"; \ + \ + if (dst + 4 > dst_end) \ + goto memory_shortage; \ + *dst++ = ISO_CODE_ESC; \ + if (charset->dimension == 1) \ + { \ + if (charset->code_range[0] != 32 \ + && charset->code_range[1] != 255) \ + *dst++ = (unsigned char) (intermediate_char_94[reg]); \ + else \ + *dst++ = (unsigned char) (intermediate_char_96[reg]); \ + } \ + else \ + { \ + *dst++ = '$'; \ + if (charset->code_range[0] != 32 \ + && charset->code_range[1] != 255) \ + { \ + if (spec->flags & MCODING_ISO_LONG_FORM \ + || reg != 0 \ + || charset->final_byte < '@' || charset->final_byte > 'B') \ + *dst++ = (unsigned char) (intermediate_char_94[reg]); \ + } \ + else \ + *dst++ = (unsigned char) (intermediate_char_96[reg]); \ + } \ + *dst++ = charset->final_byte; \ + \ + status->designation[reg] = charset; \ + } while (0) + + +/* The following two macros produce codes (control character or escape + sequence) for ISO-2022 single-shift functions (single-shift-2 and + single-shift-3). */ + +#define ISO2022_ENCODE_SINGLE_SHIFT_2(spec, status) \ + do { \ + if (dst + 2 > dst_end) \ + goto memory_shortage; \ + if (! (spec->flags & MCODING_ISO_EIGHT_BIT)) \ + *dst++ = ISO_CODE_ESC, *dst++ = 'N'; \ + else \ + *dst++ = ISO_CODE_SS2; \ + status->single_shifting = 1; \ + } while (0) + + +#define ISO2022_ENCODE_SINGLE_SHIFT_3(spec, status) \ + do { \ + if (dst + 2 > dst_end) \ + goto memory_shortage; \ + if (! (spec->flags & MCODING_ISO_EIGHT_BIT)) \ + *dst++ = ISO_CODE_ESC, *dst++ = 'O'; \ + else \ + *dst++ = ISO_CODE_SS3; \ + status->single_shifting = 1; \ + } while (0) + + +/* The following four macros produce codes (control character or + escape sequence) for ISO-2022 locking-shift functions (shift-in, + shift-out, locking-shift-2, and locking-shift-3). */ + +#define ISO2022_ENCODE_SHIFT_IN(status) \ + do { \ + if (dst + 1 > dst_end) \ + goto memory_shortage; \ + *dst++ = ISO_CODE_SI; \ + status->invocation[0] = 0; \ + } while (0) + + +#define ISO2022_ENCODE_SHIFT_OUT(status) \ + do { \ + if (dst + 1 > dst_end) \ + goto memory_shortage; \ + *dst++ = ISO_CODE_SO; \ + status->invocation[0] = 1; \ + } while (0) + + +#define ISO2022_ENCODE_LOCKING_SHIFT_2(status) \ + do { \ + if (dst + 2 > dst_end) \ + goto memory_shortage; \ + *dst++ = ISO_CODE_ESC, *dst++ = 'n'; \ + status->invocation[0] = 2; \ + } while (0) + + +#define ISO2022_ENCODE_LOCKING_SHIFT_3(status) \ + do { \ + if (dst + 2 > dst_end) \ + goto memory_shortage; \ + *dst++ = ISO_CODE_ESC, *dst++ = 'o'; \ + status->invocation[0] = 3; \ + } while (0) + +#define ISO2022_ENCODE_UTF8_SHIFT_START(len) \ + do { \ + CHECK_DST (3 + len); \ + *dst++ = ISO_CODE_ESC; \ + *dst++ = '%'; \ + *dst++ = 'G'; \ + status->utf8_shifting = 1; \ + } while (0) + + +#define ISO2022_ENCODE_UTF8_SHIFT_END() \ + do { \ + CHECK_DST (3); \ + *dst++ = ISO_CODE_ESC; \ + *dst++ = '%'; \ + *dst++ = '@'; \ + status->utf8_shifting = 0; \ + } while (0) + + +#define ISO2022_ENCODE_NON_STANDARD(name, len) \ + do { \ + CHECK_DST (6 + len + 1 + non_standard_charset_bytes); \ + non_standard_begin = dst; \ + *dst++ = ISO_CODE_ESC; \ + *dst++ = '%'; \ + *dst++ = '/'; \ + *dst++ = '0' + non_standard_charset_bytes; \ + *dst++ = 0, *dst++ = 0; /* filled later */ \ + memcpy (dst, name, len); \ + dst += len; \ + *dst++ = ISO_CODE_STX; \ + non_standard_bytes = len + 1; \ + } while (0) + + +static char * +find_ctext_non_standard_name (MCharset *charset, int *bytes) +{ + char *name = msymbol_name (charset->name); + + if (! strcmp (name, "koi8-r")) + *bytes = 1; + else if (! strcmp (name, "big5")) + name = "big5-0", *bytes = 2; + else + return NULL; + return name; +} + +/* Designate CHARSET to a graphic register specified in + SPEC->designation. If the register is not yet invoked to graphic + left not right, invoke it to graphic left. DSTP points to a + variable containing a memory address where the output must go. + DST_END is the limit of that memory. + + Return 0 if it succeeds. Return -1 otherwise, which means that the + memory area is too short. By side effect, update the variable that + DSTP points to. */ + +static int +iso_2022_designate_invoke_charset (MCodingSystem *coding, + MCharset *charset, + struct iso_2022_spec *spec, + struct iso_2022_status *status, + unsigned char **dstp, + unsigned char *dst_end) +{ + int i; + unsigned char *dst = *dstp; + + for (i = 0; i < 4; i++) + if (charset == status->designation[i]) + break; + + if (i >= 4) + { + /* CHARSET is not yet designated to any graphic registers. */ + for (i = 0; i < coding->ncharsets; i++) + if (charset == coding->charsets[i]) + break; + if (i == coding->ncharsets) + { + for (i = 0; i < mcharset__iso_2022_table.used; i++) + if (charset == mcharset__iso_2022_table.charsets[i]) + break; + i += coding->ncharsets; + } + i = spec->designations[i]; + ISO2022_ENCODE_DESIGNATION (i, charset, spec, status); + } + + if (status->invocation[0] != i + && status->invocation[1] != i) + { + /* Graphic register I is not yet invoked. */ + switch (i) + { + case 0: /* graphic register 0 */ + ISO2022_ENCODE_SHIFT_IN (status); + break; + + case 1: /* graphic register 1 */ + ISO2022_ENCODE_SHIFT_OUT (status); + break; + + case 2: /* graphic register 2 */ + if (spec->flags & MCODING_ISO_SINGLE_SHIFT) + ISO2022_ENCODE_SINGLE_SHIFT_2 (spec, status); + else + ISO2022_ENCODE_LOCKING_SHIFT_2 (status); + break; + + case 3: /* graphic register 3 */ + if (spec->flags & MCODING_ISO_SINGLE_SHIFT) + ISO2022_ENCODE_SINGLE_SHIFT_3 (spec, status); + else + ISO2022_ENCODE_LOCKING_SHIFT_3 (status); + break; + } + } + *dstp = dst; + return 0; + + memory_shortage: + *dstp = dst; + return -1; +} + + +/* Reset the invocation/designation status to the initial one. SPEC + and STATUS contain information about the current and initial + invocation /designation status respectively. DSTP points to a + variable containing a memory address where the output must go. + DST_END is the limit of that memory. + + Return 0 if it succeeds. Return -1 otherwise, which means that the + memory area is too short. By side effect, update the variable that + DSTP points to. */ + +static int +iso_2022_reset_invocation_designation (struct iso_2022_spec *spec, + struct iso_2022_status *status, + unsigned char **dstp, + unsigned char *dst_end) +{ + unsigned char *dst = *dstp; + int i; + + /* Reset the invocation status of GL. We have not yet supported GR + invocation. */ + if (status->invocation[0] != spec->initial_invocation[0] + && spec->initial_invocation[0] >= 0) + { + if (spec->initial_invocation[0] == 0) + ISO2022_ENCODE_SHIFT_IN (status); + else if (spec->initial_invocation[0] == 1) + ISO2022_ENCODE_SHIFT_OUT (status); + else if (spec->initial_invocation[0] == 2) + ISO2022_ENCODE_LOCKING_SHIFT_2 (status); + else /* i.e. spec->initial_invocation[0] == 3 */ + ISO2022_ENCODE_LOCKING_SHIFT_3 (status); + } + + /* Reset the designation status of G0..G3. */ + for (i = 0; i < 4; i++) + if (status->designation[i] != spec->initial_designation[i] + && spec->initial_designation[i]) + { + MCharset *charset = spec->initial_designation[i]; + + ISO2022_ENCODE_DESIGNATION (i, charset, spec, status); + } + + *dstp = dst; + return 0; + + memory_shortage: + *dstp = dst; + return -1; +} + + +static int +encode_coding_iso_2022 (MText *mt, int from, int to, + unsigned char *destination, int dst_bytes, + MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + MCodingSystem *coding = internal->coding; + unsigned char *src, *src_end; + unsigned char *dst = destination; + unsigned char *dst_end = dst + dst_bytes; + int nchars = 0; + unsigned char *dst_base; + struct iso_2022_spec *spec = (struct iso_2022_spec *) coding->extra_spec; + int full_support = spec->flags & MCODING_ISO_FULL_SUPPORT; + struct iso_2022_status *status + = (struct iso_2022_status *) &(converter->status); + MCharset *primary, *charset0, *charset1; + int next_primary_change; + int ncharsets = coding->ncharsets; + MCharset **charsets = coding->charsets; + MCharset *cns_charsets[15]; + int ascii_compatible = coding->ascii_compatible; + MCharset *non_standard_charset = NULL; + int non_standard_charset_bytes = 0; + int non_standard_bytes = 0; + unsigned char *non_standard_begin = NULL; + enum MTextFormat format = mt->format; + + SET_SRC (mt, format, from, to); + + if (spec->flags & MCODING_ISO_EUC_TW_SHIFT) + { + int i; + + memset (cns_charsets, 0, sizeof (cns_charsets)); + for (i = 0; i < ncharsets; i++) + if (charsets[i]->dimension == 2) + { + int final = charsets[i]->final_byte; + + if (final >= 'G' && final <= 'M') + cns_charsets[final - 'G'] = charsets[i]; + else if (final < 0) + cns_charsets[14] = charsets[i]; + } + } + + next_primary_change = from; + primary = NULL; + charset0 = status->designation[status->invocation[0]]; + charset1 = (status->invocation[1] < 0 ? NULL + : status->designation[status->invocation[1]]); + + while (1) + { + int bytes, c; + + dst_base = dst; + ONE_MORE_CHAR (c, bytes, format); + + if (c < 128 && ascii_compatible) + { + if (status->utf8_shifting) + ISO2022_ENCODE_UTF8_SHIFT_END (); + CHECK_DST (1); + *dst++ = c; + } + else if (c <= 32 || c == 127) + { + if (status->utf8_shifting) + ISO2022_ENCODE_UTF8_SHIFT_END (); + if (spec->flags & MCODING_ISO_RESET_AT_CNTL + || (c == '\n' && spec->flags & MCODING_ISO_RESET_AT_EOL)) + { + if (iso_2022_reset_invocation_designation (spec, status, + &dst, dst_end) < 0) + goto insufficient_destination; + charset0 = status->designation[status->invocation[0]]; + charset1 = (status->invocation[1] < 0 ? NULL + : status->designation[status->invocation[1]]); + } + CHECK_DST (1); + *dst++ = c; + } + else + { + unsigned code = MCHAR_INVALID_CODE; + MCharset *charset = NULL; + int gr_mask; + int pos = from + nchars; + + if (pos >= next_primary_change) + { + MSymbol primary_charset + = (MSymbol) mtext_get_prop (mt, pos, Mcharset); + primary = MCHARSET (primary_charset); + if (primary && primary != mcharset__binary) + { + if (primary->final_byte <= 0) + primary = NULL; + else if (! full_support) + { + int i; + + for (i = 0; i < ncharsets; i++) + if (primary == charsets[i]) + break; + if (i == ncharsets) + primary = NULL; + } + } + + mtext_prop_range (mt, Mcharset, pos, + NULL, &next_primary_change, 0); + } + + if (primary && primary != mcharset__binary) + { + code = ENCODE_CHAR (primary, c); + if (code != MCHAR_INVALID_CODE) + charset = primary; + } + if (! charset) + { + if (c <= 32 || c == 127) + { + code = c; + charset = mcharset__ascii; + } + else + { + int i; + + for (i = 0; i < ncharsets; i++) + { + charset = charsets[i]; + code = ENCODE_CHAR (charset, c); + if (code != MCHAR_INVALID_CODE) + break; + } + if (i == ncharsets) + { + if (spec->flags & MCODING_ISO_FULL_SUPPORT) + { + for (i = 0; i < mcharset__iso_2022_table.used; i++) + { + charset = mcharset__iso_2022_table.charsets[i]; + code = ENCODE_CHAR (charset, c); + if (code != MCHAR_INVALID_CODE) + break; + } + if (i == mcharset__iso_2022_table.used) + { + if (spec->flags & MCODING_ISO_DESIGNATION_CTEXT_EXT) + goto unsupported_char; + converter->result = MCONVERSION_RESULT_INVALID_CHAR; + goto finish; + } + } + else + goto unsupported_char; + } + } + } + + if (charset + && (charset->final_byte >= 0 + || spec->flags & MCODING_ISO_EUC_TW_SHIFT)) + { + if (code >= 0x80 && code < 0xA0) + goto unsupported_char; + code &= 0x7F7F7F7F; + if (status->utf8_shifting) + ISO2022_ENCODE_UTF8_SHIFT_END (); + if (charset == charset0) + gr_mask = 0; + else if (charset == charset1) + gr_mask = 0x80; + else + { + unsigned char *p = NULL; + + if (spec->flags & MCODING_ISO_EUC_TW_SHIFT) + { + int i; + + if (cns_charsets[0] == charset) + { + CHECK_DST (2); + } + else + { + for (i = 1; i < 15; i++) + if (cns_charsets[i] == charset) + break; + CHECK_DST (4); + *dst++ = ISO_CODE_SS2; + *dst++ = 0xA1 + i; + } + status->single_shifting = 1; + p = dst; + } + else + { + if (iso_2022_designate_invoke_charset + (coding, charset, spec, status, &dst, dst_end) < 0) + goto insufficient_destination; + charset0 = status->designation[status->invocation[0]]; + charset1 = (status->invocation[1] < 0 ? NULL + : status->designation[status->invocation[1]]); + } + if (status->single_shifting) + gr_mask + = (spec->flags & MCODING_ISO_EIGHT_BIT) ? 0x80 : 0; + else if (charset == charset0) + gr_mask = 0; + else + gr_mask = 0x80; + } + if (charset->dimension == 1) + { + CHECK_DST (1); + *dst++ = code | gr_mask; + } + else if (charset->dimension == 2) + { + CHECK_DST (2); + *dst++ = (code >> 8) | gr_mask; + *dst++ = (code & 0xFF) | gr_mask; + } + else + { + CHECK_DST (3); + *dst++ = (code >> 16) | gr_mask; + *dst++ = ((code >> 8) & 0xFF) | gr_mask; + *dst++ = (code & 0xFF) | gr_mask; + } + status->single_shifting = 0; + } + else if (charset && spec->flags & MCODING_ISO_DESIGNATION_CTEXT_EXT) + { + if (charset != non_standard_charset) + { + char *name = (find_ctext_non_standard_name + (charset, &non_standard_charset_bytes)); + + if (name) + { + int len = strlen (name); + + ISO2022_ENCODE_NON_STANDARD (name, len); + non_standard_charset = charset; + } + else + non_standard_charset = NULL; + } + + if (non_standard_charset) + { + if (dst + non_standard_charset_bytes > dst_end) + goto insufficient_destination; + non_standard_bytes += non_standard_charset_bytes; + non_standard_begin[4] = (non_standard_bytes / 128) | 0x80; + non_standard_begin[5] = (non_standard_bytes % 128) | 0x80; + if (non_standard_charset_bytes == 1) + *dst++ = code; + else if (non_standard_charset_bytes == 2) + *dst++ = code >> 8, *dst++ = code & 0xFF; + else if (non_standard_charset_bytes == 3) + *dst++ = code >> 16, *dst++ = (code >> 8) & 0xFF, + *dst++ = code & 0xFF; + else /* i.e non_standard_charset_bytes == 3 */ + *dst++ = code >> 24, *dst++ = (code >> 16) & 0xFF, + *dst++ = (code >> 8) & 0xFF, *dst++ = code & 0xFF; + } + else + { + int len = CHAR_BYTES (c); + + if (c >= 0x110000) + goto unsupported_char; + if (! status->utf8_shifting) + ISO2022_ENCODE_UTF8_SHIFT_START (len); + else + CHECK_DST (len); + CHAR_STRING (c, dst); + } + } + else + goto unsupported_char; + } + src += bytes; + nchars++; + continue; + + unsupported_char: + { + int len; + + if (iso_2022_designate_invoke_charset (coding, mcharset__ascii, + spec, status, + &dst, dst_end) < 0) + goto insufficient_destination; + if (! converter->lenient) + break; + len = encode_unsupporeted_char (c, dst, dst_end, mt, from + nchars); + if (len == 0) + goto insufficient_destination; + dst += len; + src += bytes; + nchars++; + } + } + /* We reach here because of an unsupported char. */ + converter->result = MCONVERSION_RESULT_INVALID_CHAR; + goto finish; + + insufficient_destination: + dst = dst_base; + converter->result = MCONVERSION_RESULT_INSUFFICIENT_DST; + + finish: + if (converter->result == MCONVERSION_RESULT_SUCCESS + && converter->last_block) + { + if (status->utf8_shifting) + { + ISO2022_ENCODE_UTF8_SHIFT_END (); + dst_base = dst; + } + if (spec->flags & MCODING_ISO_RESET_AT_EOL + && charset0 != spec->initial_designation[0]) + { + if (iso_2022_reset_invocation_designation (spec, status, + &dst, dst_end) < 0) + goto insufficient_destination; + } + } + converter->nchars += nchars; + converter->nbytes += dst - destination; + return (converter->result == MCONVERSION_RESULT_INVALID_CHAR ? -1 : 0); +} + + +/* Staffs for coding-systems of type MCODING_TYPE_MISC. */ + +/* For SJIS handling... */ + +#define SJIS_TO_JIS(s1, s2) \ + (s2 >= 0x9F \ + ? (((s1 * 2 - (s1 >= 0xE0 ? 0x160 : 0xE0)) << 8) \ + | (s2 - 0x7E)) \ + : (((s1 * 2 - ((s1 >= 0xE0) ? 0x161 : 0xE1)) << 8) \ + | (s2 - ((s2 >= 0x7F) ? 0x20 : 0x1F)))) + +#define JIS_TO_SJIS(c1, c2) \ + ((c1 & 1) \ + ? (((c1 / 2 + ((c1 < 0x5F) ? 0x71 : 0xB1)) << 8) \ + | (c2 + ((c2 >= 0x60) ? 0x20 : 0x1F))) \ + : (((c1 / 2 + ((c1 < 0x5F) ? 0x70 : 0xB0)) << 8) \ + | (c2 + 0x7E))) + + +static int +reset_coding_sjis (MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + MCodingSystem *coding = internal->coding; + + if (! coding->ready) + { + MSymbol kanji_sym = msymbol ("jisx0208.1983"); + MCharset *kanji = MCHARSET (kanji_sym); + MSymbol kana_sym = msymbol ("jisx0201-kana"); + MCharset *kana = MCHARSET (kana_sym); + + if (! kanji || ! kana) + return -1; + coding->ncharsets = 3; + coding->charsets[1] = kanji; + coding->charsets[2] = kana; + } + coding->ready = 1; + return 0; +} + +static int +decode_coding_sjis (const unsigned char *source, int src_bytes, MText *mt, + MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + MCodingSystem *coding = internal->coding; + const unsigned char *src = internal->carryover; + const unsigned char *src_stop = src + internal->carryover_bytes; + const unsigned char *src_end = source + src_bytes; + const unsigned char *src_base; + unsigned char *dst = mt->data + mt->nbytes; + unsigned char *dst_end = mt->data + mt->allocated - MAX_UTF8_CHAR_BYTES; + int nchars = 0; + int last_nchars = 0; + int at_most = converter->at_most > 0 ? converter->at_most : -1; + + MCharset *charset_roman = coding->charsets[0]; + MCharset *charset_kanji = coding->charsets[1]; + MCharset *charset_kana = coding->charsets[2]; + MCharset *charset = mcharset__ascii; + int error = 0; + + while (1) + { + MCharset *this_charset; + int c, c1, c2; + + ONE_MORE_BASE_BYTE (c1); + + c2 = -1; + if (c1 < 0x80) + { + this_charset = ((c1 <= 0x20 || c1 == 0x7F) + ? mcharset__ascii + : charset_roman); + } + else if ((c1 >= 0x81 && c1 <= 0x9F) || (c1 >= 0xE0 && c1 <= 0xEF)) + { + ONE_MORE_BYTE (c2); + if ((c2 >= 0x40 && c2 <= 0x7F) || (c2 >= 80 && c2 <= 0xFC)) + { + this_charset = charset_kanji; + c1 = SJIS_TO_JIS (c1, c2); + } + else + goto invalid_byte; + } + else if (c1 >= 0xA1 && c1 <= 0xDF) + { + this_charset = charset_kana; + c1 &= 0x7F; + } + else + goto invalid_byte; + + c = DECODE_CHAR (this_charset, c1); + if (c >= 0) + goto emit_char; + + invalid_byte: + if (! converter->lenient) + break; + REWIND_SRC_TO_BASE (); + c = *src++; + this_charset = mcharset__binary; + + emit_char: + if (this_charset != mcharset__ascii + && this_charset != charset) + { + TAKEIN_CHARS (mt, nchars - last_nchars, + dst - (mt->data + mt->nbytes), charset); + charset = this_charset; + last_nchars = nchars; + } + EMIT_CHAR (c); + } + /* We reach here because of an invalid byte. */ + error = 1; + + source_end: + TAKEIN_CHARS (mt, nchars - last_nchars, + dst - (mt->data + mt->nbytes), charset); + return finish_decoding (mt, converter, nchars, + source, src_end, src_base, error); +} + +static int +encode_coding_sjis (MText *mt, int from, int to, + unsigned char *destination, int dst_bytes, + MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + MCodingSystem *coding = internal->coding; + unsigned char *src, *src_end; + unsigned char *dst = destination; + unsigned char *dst_end = dst + dst_bytes; + int nchars = 0; + MCharset *charset_roman = coding->charsets[0]; + MCharset *charset_kanji = coding->charsets[1]; + MCharset *charset_kana = coding->charsets[2]; + enum MTextFormat format = mt->format; + + SET_SRC (mt, format, from, to); + + while (1) + { + int c, bytes, len; + unsigned code; + + ONE_MORE_CHAR (c, bytes, format); + + if (c <= 0x20 || c == 0x7F) + { + CHECK_DST (1); + *dst++ = c; + } + else + { + if ((code = ENCODE_CHAR (charset_roman, c)) != MCHAR_INVALID_CODE) + { + CHECK_DST (1); + *dst++ = c; + } + else if ((code = ENCODE_CHAR (charset_kanji, c)) + != MCHAR_INVALID_CODE) + { + int c1 = code >> 8, c2 = code & 0xFF; + code = JIS_TO_SJIS (c1, c2); + CHECK_DST (2); + *dst++ = code >> 8; + *dst++ = code & 0xFF; + } + else if ((code = ENCODE_CHAR (charset_kana, c)) + != MCHAR_INVALID_CODE) + { + CHECK_DST (1); + *dst++ = code | 0x80; + } + else + { + if (! converter->lenient) + break; + len = encode_unsupporeted_char (c, dst, dst_end, + mt, from + nchars); + if (len == 0) + goto insufficient_destination; + dst += len; + } + } + src += bytes; + nchars++; + } + /* We reach here because of an unsupported char. */ + converter->result = MCONVERSION_RESULT_INVALID_CHAR; + goto finish; + + insufficient_destination: + converter->result = MCONVERSION_RESULT_INSUFFICIENT_DST; + + finish: + converter->nchars += nchars; + converter->nbytes += dst - destination; + return (converter->result == MCONVERSION_RESULT_INVALID_CHAR ? -1 : 0); +} + + +static MCodingSystem * +find_coding (MSymbol name) +{ + MCodingSystem *coding = (MCodingSystem *) msymbol_get (name, Mcoding); + + if (! coding) + { + MPlist *plist, *pl; + MSymbol sym = msymbol__canonicalize (name); + + plist = mplist_find_by_key (coding_definition_list, sym); + if (! plist) + return NULL; + pl = MPLIST_PLIST (plist); + name = MPLIST_VAL (pl); + mconv_define_coding (MSYMBOL_NAME (name), MPLIST_NEXT (pl), + NULL, NULL, NULL, NULL); + coding = (MCodingSystem *) msymbol_get (name, Mcoding); + plist = mplist_pop (plist); + M17N_OBJECT_UNREF (plist); + } + return coding; +} + +#define BINDING_NONE 0 +#define BINDING_BUFFER 1 +#define BINDING_STREAM 2 + +#define CONVERT_WORKSIZE 0x10000 + + +/* Internal API */ + +int +mcoding__init (void) +{ + int i; + MPlist *param, *charsets, *pl; + + MLIST_INIT1 (&coding_list, codings, 128); + coding_definition_list = mplist (); + + /* ISO-2022 specific initialize routine. */ + for (i = 0; i < 0x20; i++) + iso_2022_code_class[i] = ISO_control_0; + for (i = 0x21; i < 0x7F; i++) + iso_2022_code_class[i] = ISO_graphic_plane_0; + for (i = 0x80; i < 0xA0; i++) + iso_2022_code_class[i] = ISO_control_1; + for (i = 0xA1; i < 0xFF; i++) + iso_2022_code_class[i] = ISO_graphic_plane_1; + iso_2022_code_class[0x20] = iso_2022_code_class[0x7F] = ISO_0x20_or_0x7F; + iso_2022_code_class[0xA0] = iso_2022_code_class[0xFF] = ISO_0xA0_or_0xFF; + iso_2022_code_class[0x0E] = ISO_shift_out; + iso_2022_code_class[0x0F] = ISO_shift_in; + iso_2022_code_class[0x19] = ISO_single_shift_2_7; + iso_2022_code_class[0x1B] = ISO_escape; + iso_2022_code_class[0x8E] = ISO_single_shift_2; + iso_2022_code_class[0x8F] = ISO_single_shift_3; + iso_2022_code_class[0x9B] = ISO_control_sequence_introducer; + + Mcoding = msymbol ("coding"); + + Mutf = msymbol ("utf"); + Miso_2022 = msymbol ("iso-2022"); + + Mreset_at_eol = msymbol ("reset-at-eol"); + Mreset_at_cntl = msymbol ("reset-at-cntl"); + Meight_bit = msymbol ("eight-bit"); + Mlong_form = msymbol ("long-form"); + Mdesignation_g0 = msymbol ("designation-g0"); + Mdesignation_g1 = msymbol ("designation-g1"); + Mdesignation_ctext = msymbol ("designation-ctext"); + Mdesignation_ctext_ext = msymbol ("designation-ctext-ext"); + Mlocking_shift = msymbol ("locking-shift"); + Msingle_shift = msymbol ("single-shift"); + Msingle_shift_7 = msymbol ("single-shift-7"); + Meuc_tw_shift = msymbol ("euc-tw-shift"); + Miso_6429 = msymbol ("iso-6429"); + Mrevision_number = msymbol ("revision-number"); + Mfull_support = msymbol ("full-support"); + Mmaybe = msymbol ("maybe"); + + Mtype = msymbol ("type"); + Mcharsets = msymbol_as_managing_key ("charsets"); + Mflags = msymbol_as_managing_key ("flags"); + Mdesignation = msymbol_as_managing_key ("designation"); + Minvocation = msymbol_as_managing_key ("invocation"); + Mcode_unit = msymbol ("code-unit"); + Mbom = msymbol ("bom"); + Mlittle_endian = msymbol ("little-endian"); + + param = mplist (); + charsets = mplist (); + pl = param; + /* Setup predefined codings. */ + mplist_set (charsets, Msymbol, Mcharset_ascii); + pl = mplist_add (pl, Mtype, Mcharset); + pl = mplist_add (pl, Mcharsets, charsets); + Mcoding_us_ascii = mconv_define_coding ("us-ascii", param, + NULL, NULL, NULL, NULL); + + { + MSymbol alias = msymbol ("ANSI_X3.4-1968"); + MCodingSystem *coding + = (MCodingSystem *) msymbol_get (Mcoding_us_ascii, Mcoding); + + msymbol_put (alias, Mcoding, coding); + alias = msymbol__canonicalize (alias); + msymbol_put (alias, Mcoding, coding); + } + + mplist_set (charsets, Msymbol, Mcharset_iso_8859_1); + Mcoding_iso_8859_1 = mconv_define_coding ("iso-8859-1", param, + NULL, NULL, NULL, NULL); + + mplist_set (charsets, Msymbol, Mcharset_m17n); + mplist_put (param, Mtype, Mutf); + mplist_put (param, Mcode_unit, (void *) 8); + Mcoding_utf_8_full = mconv_define_coding ("utf-8-full", param, + NULL, NULL, NULL, NULL); + + mplist_set (charsets, Msymbol, Mcharset_unicode); + Mcoding_utf_8 = mconv_define_coding ("utf-8", param, + NULL, NULL, NULL, NULL); + + mplist_put (param, Mcode_unit, (void *) 16); + mplist_put (param, Mbom, Mmaybe); +#ifndef WORDS_BIGENDIAN + mplist_put (param, Mlittle_endian, Mt); +#endif + Mcoding_utf_16 = mconv_define_coding ("utf-16", param, + NULL, NULL, NULL, NULL); + + mplist_put (param, Mcode_unit, (void *) 32); + Mcoding_utf_32 = mconv_define_coding ("utf-32", param, + NULL, NULL, NULL, NULL); + + mplist_put (param, Mcode_unit, (void *) 16); + mplist_put (param, Mbom, Mnil); + mplist_put (param, Mlittle_endian, Mnil); + Mcoding_utf_16be = mconv_define_coding ("utf-16be", param, + NULL, NULL, NULL, NULL); + + mplist_put (param, Mcode_unit, (void *) 32); + Mcoding_utf_32be = mconv_define_coding ("utf-32be", param, + NULL, NULL, NULL, NULL); + + mplist_put (param, Mcode_unit, (void *) 16); + mplist_put (param, Mlittle_endian, Mt); + Mcoding_utf_16le = mconv_define_coding ("utf-16le", param, + NULL, NULL, NULL, NULL); + + mplist_put (param, Mcode_unit, (void *) 32); + Mcoding_utf_32le = mconv_define_coding ("utf-32le", param, + NULL, NULL, NULL, NULL); + + mplist_put (param, Mtype, Mnil); + pl = mplist (); + mplist_add (pl, Msymbol, msymbol ("Shift_JIS")); + mplist_put (param, Maliases, pl); + mplist_set (charsets, Msymbol, Mcharset_ascii); + Mcoding_sjis = mconv_define_coding ("sjis", param, + reset_coding_sjis, + decode_coding_sjis, + encode_coding_sjis, NULL); + + M17N_OBJECT_UNREF (charsets); + M17N_OBJECT_UNREF (param); + M17N_OBJECT_UNREF (pl); + + return 0; +} + +void +mcoding__fini (void) +{ + int i; + MPlist *plist; + + for (i = 0; i < coding_list.used; i++) + { + MCodingSystem *coding = coding_list.codings[i]; + + if (coding->extra_info) + free (coding->extra_info); + if (coding->extra_spec) + { + if (coding->type == Miso_2022) + free (((struct iso_2022_spec *) coding->extra_spec)->designations); + free (coding->extra_spec); + } + free (coding); + } + MLIST_FREE1 (&coding_list, codings); + MPLIST_DO (plist, coding_definition_list) + M17N_OBJECT_UNREF (MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (coding_definition_list); +} + +void +mconv__register_charset_coding (MSymbol sym) +{ + MSymbol name = msymbol__canonicalize (sym); + + if (! mplist_find_by_key (coding_definition_list, name)) + { + MPlist *param = mplist (), *charsets = mplist (); + + mplist_set (charsets, Msymbol, sym); + mplist_add (param, Msymbol, sym); + mplist_add (param, Mtype, Mcharset); + mplist_add (param, Mcharsets, charsets); + mplist_put (coding_definition_list, name, param); + M17N_OBJECT_UNREF (charsets); + } +} + + +int +mcoding__load_from_database () +{ + MDatabase *mdb = mdatabase_find (msymbol ("coding-list"), Mnil, Mnil, Mnil); + MPlist *def_list, *plist; + MPlist *definitions = coding_definition_list; + int mdebug_flag = MDEBUG_CODING; + + if (! mdb) + return 0; + MDEBUG_PUSH_TIME (); + def_list = (MPlist *) mdatabase_load (mdb); + MDEBUG_PRINT_TIME ("CODING", (mdebug__output, " to load the data.")); + MDEBUG_POP_TIME (); + if (! def_list) + return -1; + + MDEBUG_PUSH_TIME (); + MPLIST_DO (plist, def_list) + { + MPlist *pl, *aliases; + MSymbol name, canonicalized; + + if (! MPLIST_PLIST_P (plist)) + MERROR (MERROR_CHARSET, -1); + pl = MPLIST_PLIST (plist); + if (! MPLIST_SYMBOL_P (pl)) + MERROR (MERROR_CHARSET, -1); + name = MPLIST_SYMBOL (pl); + canonicalized = msymbol__canonicalize (name); + pl = mplist__from_plist (MPLIST_NEXT (pl)); + mplist_push (pl, Msymbol, name); + definitions = mplist_add (definitions, canonicalized, pl); + aliases = mplist_get (pl, Maliases); + if (aliases) + MPLIST_DO (aliases, aliases) + if (MPLIST_SYMBOL_P (aliases)) + { + name = MPLIST_SYMBOL (aliases); + canonicalized = msymbol__canonicalize (name); + definitions = mplist_add (definitions, canonicalized, pl); + M17N_OBJECT_REF (pl); + } + } + + M17N_OBJECT_UNREF (def_list); + MDEBUG_PRINT_TIME ("CODING", (mdebug__output, " to parse the loaded data.")); + MDEBUG_POP_TIME (); + return 0; +} + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/* External API */ + +/*** @addtogroup m17nConv */ +/*** @{ */ +/*=*/ + +/***en @name Variables: Symbols representing coding systems */ +/***ja @name �ѿ�: ����Ѥߥ����ɷϤ���ꤹ�뤿��Υ���ܥ� */ +/*** @{ */ +/*=*/ + +/***en + @brief Symbol for the coding system US-ASCII. + + The symbol #Mcoding_us_ascii has name "us-ascii" and + represents a coding system for the CES US-ASCII. */ + +/***ja + @brief US-ASCII �����ɷϤΥ���ܥ�. + + ����ܥ� #Mcoding_us_ascii �� "us-ascii" �Ȥ���̾��������� + CES US-ASCII �ѤΥ����ɷϤ򼨤��� + */ +MSymbol Mcoding_us_ascii; +/*=*/ + +/***en + @brief Symbol for the coding system ISO-8859-1. + + The symbol #Mcoding_iso_8859_1 has name "iso-8859-1" and + represents a coding system for the CES ISO-8859-1. */ + +/***ja + @brief ISO-8859-1 �����ɷϤΥ���ܥ�. + + ����ܥ� #Mcoding_iso_8859_1 �� "iso-8859-1" + �Ȥ���̾���������CES ISO-8859-1 �ѤΥ����ɷϤ򼨤��� */ + +MSymbol Mcoding_iso_8859_1; +/*=*/ + +/***en + @brief Symbol for the coding system UTF-8. + + The symbol #Mcoding_utf_8 has name "utf-8" and represents + a coding system for the CES UTF-8. */ + +/***ja + @brief UTF-8 �����ɷϤΥ���ܥ�. + + ����ܥ� #Mcoding_utf_8 �� "utf-8" �Ȥ���̾���������CES + UTF-8 �ѤΥ����ɷϤ򼨤��� + */ + +MSymbol Mcoding_utf_8; +/*=*/ + +/***en + @brief Symbol for the coding system UTF-8-FULL. + + The symbol #Mcoding_utf_8_full has name "utf-8-full" and + represents a coding system that is a extension of UTF-8. This + coding system uses the same encoding algorithm as UTF-8 but is not + limited to the Unicode characters. It can encode all characters + supported by the m17n library. */ + +/***ja + @brief UTF-8-FULL �����ɷϤΥ���ܥ�. + + ����ܥ� #Mcoding_utf_8_full �� "utf-8-full" + �Ȥ���̾���������"UTF-8" �γ�ĥ�Ǥ��륳���ɷϤ򼨤��� + ���Υ����ɷϤ� UTF-8 ��Ʊ�����󥳡��ǥ��󥰥��르�ꥺ����Ѥ��뤬���оݤ� + Unicode ʸ���ˤϸ��ꤵ��ʤ��� + �ޤ�m17n �饤�֥�꤬�������Ƥ�ʸ���򥨥󥳡��ɤ��뤳�Ȥ��Ǥ��롣 + */ + +MSymbol Mcoding_utf_8_full; +/*=*/ + +/***en + @brief Symbol for the coding system UTF-16. + + The symbol #Mcoding_utf_16 has name "utf-16" and + represents a coding system for the CES UTF-16 (RFC 2279). */ +/***ja + @brief UTF-16 �����ɷϤΥ���ܥ�. + + ����ܥ� #Mcoding_utf_16 �� "utf-16" �Ȥ���̾��������� + CES UTF-16 (RFC 2279) �ѤΥ����ɷϤ򼨤��� + */ + +MSymbol Mcoding_utf_16; +/*=*/ + +/***en + @brief Symbol for the coding system UTF-16BE. + + The symbol #Mcoding_utf_16be has name "utf-16be" and + represents a coding system for the CES UTF-16BE (RFC 2279). */ + +/***ja + @brief UTF-16BE �����ɷϤΥ���ܥ�. + + ����ܥ� #Mcoding_utf_16be �� "utf-16be" �Ȥ���̾��������� + CES UTF-16BE (RFC 2279) �ѤΥ����ɷϤ򼨤��� */ + +MSymbol Mcoding_utf_16be; +/*=*/ + +/***en + @brief Symbol for the coding system UTF-16LE. + + The symbol #Mcoding_utf_16le has name "utf-16le" and + represents a coding system for the CES UTF-16LE (RFC 2279). */ + +/***ja + @brief UTF-16LE �����ɷϤΥ���ܥ�. + + ����ܥ� #Mcoding_utf_16le �� "utf-16le" �Ȥ���̾��������� + CES UTF-16LE (RFC 2279) �ѤΥ����ɷϤ򼨤��� */ + +MSymbol Mcoding_utf_16le; +/*=*/ + +/***en + @brief Symbol for the coding system UTF-32. + + The symbol #Mcoding_utf_32 has name "utf-32" and + represents a coding system for the CES UTF-32 (RFC 2279). */ + +/***ja + @brief UTF-32 �����ɷϤΥ���ܥ�. + + ����ܥ� #Mcoding_utf_32 �� "utf-32" �Ȥ���̾��������� + CES UTF-32 (RFC 2279) �ѤΥ����ɷϤ򼨤��� */ + +MSymbol Mcoding_utf_32; +/*=*/ + +/***en + @brief Symbol for the coding system UTF-32BE. + + The symbol #Mcoding_utf_32be has name "utf-32be" and + represents a coding system for the CES UTF-32BE (RFC 2279). */ +/***ja + @brief UTF-32BE �����ɷϤΥ���ܥ�. + + ����ܥ� #Mcoding_utf_32be �� "utf-32be" �Ȥ���̾��������� + CES UTF-32BE (RFC 2279) �ѤΥ����ɷϤ򼨤��� */ + +MSymbol Mcoding_utf_32be; +/*=*/ + +/***en + @brief Symbol for the coding system UTF-32LE. + + The symbol #Mcoding_utf_32le has name "utf-32le" and + represents a coding system for the CES UTF-32LE (RFC 2279). */ +/***ja + @brief UTF-32LE �����ɷϤΥ���ܥ�. + + ����ܥ� #Mcoding_utf_32le �� "utf-32le" �Ȥ���̾��������� + CES UTF-32LE (RFC 2279) �ѤΥ����ɷϤ򼨤��� */ + +MSymbol Mcoding_utf_32le; +/*=*/ + +/***en + @brief Symbol for the coding system SJIS. + + The symbol #Mcoding_sjis has name "sjis" and represents a coding + system for the CES Shift-JIS. */ +/***ja + @brief SJIS �����ɷϤΥ���ܥ�. + + ����ܥ� #Mcoding_sjis has �� "sjis" �Ȥ���̾��������� + CES Shift-JIS�ѤΥ����ɷϤ򼨤��� */ + +MSymbol Mcoding_sjis; +/*** @} */ +/*=*/ + +/***en + @name Variables: Parameter keys for mconv_define_coding (). */ +/***ja + @name �ѿ�: mconv_define_coding () �ѥѥ�᡼������ */ +/*** @{ */ +/*=*/ + +/***en + Parameter key for mconv_define_coding () (which see). */ +/***ja + mconv_define_coding () �ѥѥ�᡼������ (�ܺ٤� mconv_define_coding ()����). */ +MSymbol Mtype; +MSymbol Mcharsets; +MSymbol Mflags; +MSymbol Mdesignation; +MSymbol Minvocation; +MSymbol Mcode_unit; +MSymbol Mbom; +MSymbol Mlittle_endian; +/*** @} */ +/*=*/ + +/***en + @name Variables: Symbols representing coding system types. */ +/***ja + @name �ѿ��� �����ɷϤΥ����פ򼨤�����ܥ�. */ +/*** @{ */ +/*=*/ + +/***en + Symbol that can be a value of the #Mtype parameter of a coding + system used in an argument to the mconv_define_coding () function + (which see). */ +/***ja + �ؿ� mconv_define_coding () �ΰ����Ȥ����Ѥ����륳���ɷϤΥѥ�᡼�� + #Mtype ���ͤȤʤ����륷��ܥ롣(�ܺ٤� + mconv_define_coding ()����)�� */ + +MSymbol Mutf; +/*=*/ +MSymbol Miso_2022; +/*=*/ +/*** @} */ +/*=*/ + +/***en + @name Variables: Symbols appearing in the value of Mflags parameter. */ +/***ja + @name �ѿ��� �ѥ�᡼�� Mflags ���ͤȤʤ����륷��ܥ�. */ +/*** @{ */ +/***en + Symbols that can be a value of the @b Mflags parameter of a coding + system used in an argument to the mconv_define_coding () function + (which see). */ +/***ja + �ؿ� mconv_define_coding () �ΰ����Ȥ����Ѥ����륳���ɷϤΥѥ�᡼�� + @b Mflags ���ͤȤʤ����륷��ܥ롣(�ܺ٤� + mconv_define_coding ()����)�� */ +MSymbol Mreset_at_eol; +MSymbol Mreset_at_cntl; +MSymbol Meight_bit; +MSymbol Mlong_form; +MSymbol Mdesignation_g0; +MSymbol Mdesignation_g1; +MSymbol Mdesignation_ctext; +MSymbol Mdesignation_ctext_ext; +MSymbol Mlocking_shift; +MSymbol Msingle_shift; +MSymbol Msingle_shift_7; +MSymbol Meuc_tw_shift; +MSymbol Miso_6429; +MSymbol Mrevision_number; +MSymbol Mfull_support; +/*** @} */ +/*=*/ + +/***en + @name Variables: Others + + Remaining variables. */ +/***ja @name �ѿ�: ����¾ + + �ۤ����ѿ��� */ +/*** @{ */ +/*=*/ +/***en + @brief Symbol whose name is "maybe". + + The variable #Mmaybe is a symbol of name "maybe". It is + used a value of @b Mbom parameter of the function + mconv_define_coding () (which see). */ +/***ja + @brief "maybe"�Ȥ���̾������ĥ���ܥ�. + + �ѿ� #Mmaybe �� "maybe" �Ȥ���̾������ġ�����ϴؿ� + mconv_define_coding () �ѥ�᡼�� @b Mbom ���ͤȤ����Ѥ����롣 + (�ܺ٤� mconv_define_coding () ����)�� */ + +MSymbol Mmaybe; +/*=*/ + +/***en + @brief The symbol @c Mcoding. + + Any decoded M-text has a text property whose key is the predefined + symbol @c Mcoding. The name of @c Mcoding is + "coding". */ + +/***ja + @brief ����ܥ� @c Mcoding. + + �ǥ����ɤ��줿 M-text �Ϥ��٤ơ�����������Ѥߥ���ܥ� @c Mcoding + �Ǥ���褦�ʥƥ����ȥץ��ѥƥ�����ġ�����ܥ� @c Mcoding �� + "coding" �Ȥ���̾������ġ� */ + +MSymbol Mcoding; +/*=*/ +/*** @} */ + +/***en + @brief Define a coding system. + + The mconv_define_coding () function defines a new coding system + and makes it accessible via a symbol whose name is $NAME. $PLIST + specifies parameters of the coding system as below: + +
    + +
  • Key is @c Mtype, value is a symbol + + The value specifies the type of the coding system. It must be + @b Mcharset, @b Mutf, @b Miso_2022, or @b Mnil. + + If the type is @b Mcharset, $EXTRA_INFO is ignored. + + If the type is @b Mutf, $EXTRA_INFO must be a pointer to + #MCodingInfoUTF. + + If the type is @b Miso_2022, $EXTRA_INFO must be a pointer to + #MCodingInfoISO2022. + + If the type is #Mnil, the argument $RESETTER, $DECODER, and + $ENCODER must be supplied. $EXTRA_INFO is ignored. Otherwise, + they can be @c NULL and the m17n library provides proper defaults. + +
  • Key is @b Mcharsets, value is a plist + + The value specifies a list charsets supported by the coding + system. The keys of the plist must be #Msymbol, and the values + must be symbols representing charsets. + +
  • Key is @b Mflags, value is a plist + + If the type is @b Miso_2022, the values specifies flags to control + the ISO 2022 interpreter. The keys of the plist must e #Msymbol, + and values must be one of the following. + +
      + +
    • @b Mreset_at_eol + + If this flag exists, designation and invocation status is reset to + the initial state at the end of line. + +
    • @b Mreset_at_cntl + + If this flag exists, designation and invocation status is reset to + the initial state at a control character. + +
    • @b Meight_bit + + If this flag exists, the graphic plane right is used. + +
    • @b Mlong_form + + If this flag exists, the over-long escape sequences (ESC '$' '(' + \) are used for designating the CCS JISX0208.1978, + GB2312, and JISX0208. + +
    • @b Mdesignation_g0 + + If this flag and @b Mfull_support exists, designates charsets not + listed in the charset list to the graphic register G0. + +
    • @b Mdesignation_g1 + + If this flag and @b Mfull_support exists, designates charsets not + listed in the charset list to the graphic register G1. + +
    • @b Mdesignation_ctext + + If this flag and @b Mfull_support exists, designates charsets not + listed in the charset list to a graphic register G0 or G1 based on + the criteria of the Compound Text. + +
    • @b Mdesignation_ctext_ext + + If this flag and @b Mfull_support exists, designates charsets not + listed in the charset list to a graphic register G0 or G1, or use + extended segment for such charsets based on the criteria of the + Compound Text. + +
    • @b Mlocking_shift + + If this flag exists, use locking shift. + +
    • @b Msingle_shift + + If this flag exists, use single shift. + +
    • @b Msingle_shift_7 + + If this flag exists, use 7-bit single shift code (0x19). + +
    • @b Meuc_tw_shift + + If this flag exists, use a special shifting according to EUC-TW. + +
    • @b Miso_6429 + + This flag is currently ignored. + +
    • @b Mrevision_number + + If this flag exists, use a revision number escape sequence to + designate a charset that has a revision number. + +
    • @b Mfull_support + + If this flag exists, support all charsets registered in the + International Registry. + +
    + +
  • Key is @b Mdesignation, value is a plist + + If the type is @b Miso_2022, the value specifies how to designate + each supported characters. The keys of the plist must be + #Minteger, and the values must be numbers indicating a graphic + registers. The Nth element value is for the Nth charset of the + charset list. The value 0..3 means that it is assumed that a + charset is already designated to the graphic register 0..3. The + negative value G (-4..-1) means that a charset is not designated + to any register at first, and if necessary, is designated to the + (G+4) graphic register. + +
  • Key is @b Minvocation, value is a plist + + If the type is @b Miso_2022, the value specifies how to invocate + each graphic registers. The plist length must be one or two. The + keys of the plist must be #Minteger, and the values must be + numbers indicating a graphic register. The value of the first + element specifies which graphic register is invocated to the + graphic plane left. If the length is one, no graphic register is + invocated to the graphic plane right. Otherwise, the value of the + second element specifies which graphic register is invocated to + the graphic plane right. + +
  • Key is @b Mcode_unit, value is an integer + + If the type is @b Mutf, the value specifies the bit length of a + code-unit. It must be 8, 16, or 32. + +
  • Key is @b Mbom, value is a symbol + + If the type is @b Mutf and the code-unit bit length is 16 or 32, + it specifies whether or not to use BOM (Byte Order Mark). If the + value is #Mnil (default), BOM is not used, else if the value is + #Mmaybe, the existence of BOM is detected at decoding time, else + BOM is used. + +
  • Key is @b Mlittle_endian, value is a symbol + + If the type is @b Mutf and the code-unit bit length is 16 or 32, + it specifies whether or not the encoding is little endian. If the + value is #Mnil (default), it is big endian, else it is little + endian. + +
+ + $RESETTER is a pointer to a function that resets a converter for + the coding system to the initial status. The pointed function is + called with one argument, a pointer to a converter object. + + $DECODER is a pointer to a function that decodes a byte sequence + according to the coding system. The pointed function is called + with four arguments: + + @li A pointer to the byte sequence to decode. + @li The number of bytes to decode. + @li A pointer to an M-text to which the decoded characters are appended. + @li A pointer to a converter object. + + $DECODER must return 0 if it succeeds. Otherwise it must return -1. + + $ENCODER is a pointer to a function that encodes an M-text + according to the coding system. The pointed function is called + with six arguments: + + @li A pointer to the M-text to encode. + @li The starting position of the encoding. + @li The ending position of the encoding. + @li A pointer to a memory area where the produced bytes are stored. + @li The size of the memory area. + @li A pointer to a converter object. + + $ENCODER must return 0 if it succeeds. Otherwise it must return -1. + + $EXTRA_INFO is a pointer to a data structure that contains extra + information about the coding system. The type of the data + structure depends on $TYPE. + + @return + + If the operation was successful, mconv_define_coding () returns a + symbol whose name is $NAME. If an error is detected, it returns + #Mnil and assigns an error code to the external variable #merror_code. */ + +/***ja + @brief �����ɷϤ��������. + + �ؿ� mconv_define_coding () �ϡ������������ɷϤ������������� + $NAME �Ȥ���̾���Υ���ܥ��ͳ�ǥ��������Ǥ���褦�ˤ��롣 $PLIST + �Ǥ�������륳���ɷϤΥѥ�᡼����ʲ��Τ褦�˻��ꤹ�롣 + +
    + +
  • ������ @c Mtype ���ͤ�����ܥ�λ� + + �ͤϥ����ɷϤΥ����פ�ɽ����@b Mcharset, @b Mutf, @b Miso_2022, #Mnil + �Τ����줫�Ǥʤ��ƤϤʤ�ʤ��� + + �����פ� @b Mcharset �ʤ�� $EXTRA_INFO ��̵�뤵��롣 + + �����פ� @b Mutf �ʤ�� $EXTRA_INFO �� #MCodingInfoUTF + �ؤΥݥ��󥿤Ǥʤ��ƤϤʤ�ʤ��� + + �����פ� @b Miso_2022�ʤ�� $EXTRA_INFO �� #MCodingInfoISO2022 + �ؤΥݥ��󥿤Ǥʤ��ƤϤʤ�ʤ��� + + �����פ� #Mnil �ʤ�С����� $RESETTER, $DECODER, $ENCODER + ��Ϳ���ʤ��ƤϤʤ�ʤ���$EXTRA_INFO ��̵�뤵��롣 + ����ʳ��ξ��ˤϤ����� @c NULL �Ǥ褯�� + m17n �饤�֥�꤬Ŭ�ڤʥǥե�����ͤ�Ϳ���롣 + +
  • ������ @b Mcharsets ���ͤ� plist �λ� + + �ͤϤ��Υ����ɷϤǥ��ݡ��Ȥ����ʸ�����åȤΥꥹ�ȤǤ��롣plist�Υ����� + #Msymbol���ͤ�ʸ�����åȤ򼨤�����ܥ�Ǥʤ��ƤϤʤ�ʤ��� + +
  • ������ @b Mflags �ͤ� plist �λ� + + �����פ� @b Miso_2022 �ʤ�С������ͤ�, ISO 2022 + ���󥿥ץ꥿�Ѥ�����ե�å��򼨤���plist �Υ����� #Msymbol + �Ǥ��ꡢ�ͤϰʲ��Τ����줫�Ǥ��롣 + +
      + +
    • @b Mreset_at_eol + + ���Υե饰������С��޷�ʸ������λؼ���ƽФϹ����ǥꥻ�åȤ��������ξ��֤���롣 + +
    • @b Mreset_at_cntl + + ���Υե饰������С��޷�ʸ������λؼ���ƽФ�����ʸ���˽в�ä������ǥꥻ�åȤ��������ξ��֤���롣 + +
    • @b Meight_bit + + ���Υե饰������С��޷�ʸ������α�Ⱦ�̤��Ѥ����롣 + +
    • @b Mlong_form + + ���Υե饰������С�ʸ������ JISX0208.1978, GB2312, JISX0208 + ��ؼ�����ݤ� over-long ���������ץ������� (ESC '$' '(' + \) ���Ѥ����롣 + +
    • @b Mdesignation_g0 + + ���Υե饰�� @b Mfull_support ������С�ʸ�����åȥꥹ�Ȥ˸����ʤ�ʸ�����åȤ� + G0 ����˻ؼ����롣 + +
    • @b Mdesignation_g1 + + ���Υե饰�� @b Mfull_support ������С�ʸ�����åȥꥹ�Ȥ˸����ʤ�ʸ�����åȤ� + G1 ����˻ؼ����롣 + +
    • @b Mdesignation_ctext + + ���Υե饰�� @b Mfull_support ������С�ʸ�����åȥꥹ�Ȥ˸����ʤ�ʸ�����åȤ� + G0 ����ޤ��� G1 ����ˡ�����ѥ���ɥƥ����Ȥδ��ˤ��äƻؼ����롣 + +
    • @b Mdesignation_ctext_ext + + ���Υե饰�� @b Mfull_support ������С�ʸ�����åȥꥹ�Ȥ˸����ʤ�ʸ�����åȤ� + G0 ����ޤ��� G1 ����ˡ����뤤�ϳ�ĥ�������Ȥ˥���ѥ���ɥƥ����Ȥδ��ˤ��äƻؼ����롣 + +
    • @b Mlocking_shift + + ���Υե饰������С����å��󥰥��եȤ��Ѥ��롣 + +
    • @b Msingle_shift + + ���Υե饰������С����󥰥륷�եȤ��Ѥ��롣 + +
    • @b Msingle_shift_7 + + ���Υե饰������С�7-bit ���󥰥륷�եȥ����� (0x19) ���Ѥ��롣 + +
    • @b Meuc_tw_shift + + ���Υե饰������С�EUC-TW �˱�ä����̤ʥ��եȤ��Ѥ��롣 + +
    • @b Miso_6429 + + �������Ǥ��Ѥ����Ƥ��ʤ��� + +
    • @b Mrevision_number + + ���Υե饰������С�revision number �����ʸ�����åȤ�ؼ�����ݤ� + revision number ���������ץ��������󥹤��Ѥ��롣 + +
    • @b Mfull_support + + ���Υե饰������С�the International Registry + ����Ͽ����Ƥ�����ʸ�����åȤ򥵥ݡ��Ȥ��롣 + +
    + +
  • ������ @b Mdesignation ���ͤ� plist �λ� + + �����פ� @b Miso_2022 �ʤ�С��ͤϳ�ʸ����ɤΤ褦�˻ؼ����뤫�򼨤��� + plist �Υ����� #Minteger���ͤϽ����graphic register�� + �򼨤������Ǥ��롣N���ܤ����Ǥ��ͤϡ�ʸ�����åȥꥹ�Ȥ� N + ���ܤ�ʸ�����åȤ��б����롣�ͤ� 0..3 �Ǥ���С�ʸ�����åȤ����Ǥ� + G0..G3 �˻ؼ� ����Ƥ��롣 + + �ͤ���(-4..-1) �Ǥ���С�������֤Ǥ�ʸ�����åȤ��ɤ��ˤ�ؼ�����Ƥ��ʤ����ȡ�ɬ�פʺݤˤ� + G0..G3 �Τ��줾��˻ؼ����뤳�Ȥ��̣���롣 + +
  • ������ @b Minvocation ���ͤ� plist �λ� + + �����פ� @b Miso_2022 �ʤ�С��ͤϳƽ����ɤΤ褦�˸ƤӽФ����򼨤��� + plist ��Ĺ���� 1 �ʤ��� 2 �Ǥ��롣plist �Υ����� + #Minteger���ͤϽ����graphic register)�򼨤������Ǥ��롣 + �ǽ�����Ǥ��ͤ��޷�ʸ�����纸Ⱦ�̤˸ƤӽФ���뽸��򼨤��� + plist ��Ĺ���� 1 �ʤ�С���Ⱦ�̤ˤϲ���ƤӽФ���ʤ��� + �����Ǥ���С����Ĥ�����Ǥ��ͤ��޷�ʸ�����籦Ⱦ�̤˸ƤӽФ���뽸��򼨤��� + +
  • ������ @b Mcode_unit ���ͤ������ͤλ� + + �����פ� @b Mutf �ʤ�С��ͤϥ����ɥ�˥åȤΥӥå�Ĺ�Ǥ��ꡢ8, 16, + 32 �Τ����줫�Ǥ��롣 + +
  • ������ @b Mbom ���ͤ�����ܥ�λ� + + �����פ� @b Mutf �ǥ����ɥ�˥åȤΥӥå�Ĺ�� 16 �� 32�ʤ�С��ͤ� + BOM (Byte Order Mark) ����Ѥ��뤫�ɤ����򼨤����ͤ��ǥե�����ͤ� + #Mnil �ʤ�С����Ѥ��ʤ����ͤ� #Mmaybe �ʤ�Хǥ����ɻ��� BOM + �����뤫�ɤ�����Ĵ�٤롣����ʳ��ʤ�л��Ѥ��롣 + +
  • ������ @b Mlittle_endian ���ͤ�����ܥ�λ� + + �����פ� @b Mutf �ǥ����ɥ�˥åȤΥӥå�Ĺ�� 16 �� 32 + �ʤ�С��ͤϥ��󥳡��ɤ� little endian ���ɤ����򼨤����ͤ��ǥե�����ͤ� + #Mnil �ʤ�� big endian �Ǥ��ꡢ�����Ǥʤ���� little endian �Ǥ��롣 + +
+ + $RESETTER + �Ϥ��Υ����ɷ��ѤΥ���С����������֤˥ꥻ�åȤ���ؿ��ؤΥݥ��󥿤Ǥ��롣 + ���δؿ��ϥ���С������֥������ȤؤΥݥ��󥿤Ȥ�����������Ȥ롣 + + $DECODER �ϥХ�����򤳤Υ����ɷϤ˽��äƥǥ����ɤ���ؿ��ؤΥݥ��󥿤Ǥ��롣 + ���δؿ��ϰʲ��Σ�������Ȥ롣 + + @li �ǥ����ɤ���Х�����ؤΥݥ��� + @li �ǥ����ɤ��٤��Х��ȿ� + @li �ǥ����ɷ�̤�ʸ�����ղä��� M-text �ؤΥݥ��� + @li ����С������֥������ȤؤΥݥ��� + + $DECODER �����������Ȥ��ˤ� 0 �򡢼��Ԥ����Ȥ��ˤ� -1 + ���֤��ʤ��ƤϤʤ�ʤ��� + + $ENCODER �� M-text �򤳤Υ����ɷϤ˽��äƥ��󥳡��ɤ���ؿ��ؤΥݥ��󥿤Ǥ��롣 + ���δؿ��ϰʲ��Σ�������Ȥ롣 + + @li ���󥳡��ɤ���M-text �ؤΥݥ��� + @li M-text �Υ��󥳡��ɳ��ϰ��� + @li M-text �Υ��󥳡��ɽ�λ���� + @li ���������Х��Ȥ��ݻ���������ΰ�ؤΥݥ��� + @li �����ΰ�Υ����� + @li ����С������֥������ȤؤΥݥ��� + + $ENCODER �����������Ȥ��ˤ� 0 �򡢼��Ԥ����Ȥ��ˤ� -1 + ���֤��ʤ��ƤϤʤ�ʤ��� + + $EXTRA_INFO �ϥ����ǥ��������ƥ�˴ؤ����ɲþ����ޤ�ǡ�����¤�ؤΥݥ��󥿤Ǥ��롣 + ���Υǡ�����¤�η� $TYPE �˰�¸���롣 + + @return + + ��������������� mconv_define_coding () �� $NAME + �Ȥ���̾���Υ���ܥ���֤��� ���顼�����Ф��줿���� #Mnil + ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 + */ + +/*** + @errors + @c MERROR_CODING */ + +MSymbol +mconv_define_coding (const char *name, MPlist *plist, + int (*resetter) (MConverter *), + int (*decoder) (const unsigned char *, int, MText *, + MConverter *), + int (*encoder) (MText *, int, int, + unsigned char *, int, + MConverter *), + void *extra_info) +{ + MSymbol sym = msymbol (name); + int i; + MCodingSystem *coding; + MPlist *pl; + + MSTRUCT_MALLOC (coding, MERROR_CODING); + coding->name = sym; + if ((coding->type = (MSymbol) mplist_get (plist, Mtype)) == Mnil) + coding->type = Mcharset; + pl = (MPlist *) mplist_get (plist, Mcharsets); + if (! pl) + MERROR (MERROR_CODING, Mnil); + coding->ncharsets = mplist_length (pl); + if (coding->ncharsets > NUM_SUPPORTED_CHARSETS) + coding->ncharsets = NUM_SUPPORTED_CHARSETS; + for (i = 0; i < coding->ncharsets; i++, pl = MPLIST_NEXT (pl)) + { + MSymbol charset_name; + + if (MPLIST_KEY (pl) != Msymbol) + MERROR (MERROR_CODING, Mnil); + charset_name = MPLIST_SYMBOL (pl); + if (! (coding->charsets[i] = MCHARSET (charset_name))) + MERROR (MERROR_CODING, Mnil); + } + + coding->resetter = resetter; + coding->decoder = decoder; + coding->encoder = encoder; + coding->ascii_compatible = 0; + coding->extra_info = extra_info; + coding->extra_spec = NULL; + coding->ready = 0; + + if (coding->type == Mcharset) + { + if (! coding->resetter) + coding->resetter = reset_coding_charset; + if (! coding->decoder) + coding->decoder = decode_coding_charset; + if (! coding->encoder) + coding->encoder = encode_coding_charset; + } + else if (coding->type == Mutf) + { + MCodingInfoUTF *info = malloc (sizeof (MCodingInfoUTF)); + MSymbol val; + + if (! coding->resetter) + coding->resetter = reset_coding_utf; + + info->code_unit_bits = (int) mplist_get (plist, Mcode_unit); + if (info->code_unit_bits == 8) + { + if (! coding->decoder) + coding->decoder = decode_coding_utf_8; + if (! coding->encoder) + coding->encoder = encode_coding_utf_8; + } + else if (info->code_unit_bits == 16) + { + if (! coding->decoder) + coding->decoder = decode_coding_utf_16; + if (! coding->encoder) + coding->encoder = encode_coding_utf_16; + } + else if (info->code_unit_bits == 32) + { + if (! coding->decoder) + coding->decoder = decode_coding_utf_32; + if (! coding->encoder) + coding->encoder = encode_coding_utf_32; + } + else + MERROR (MERROR_CODING, Mnil); + val = (MSymbol) mplist_get (plist, Mbom); + if (val == Mnil) + info->bom = 1; + else if (val == Mmaybe) + info->bom = 0; + else + info->bom = 2; + + info->endian = (mplist_get (plist, Mlittle_endian) ? 1 : 0); + coding->extra_info = info; + } + else if (coding->type == Miso_2022) + { + MCodingInfoISO2022 *info = malloc (sizeof (MCodingInfoISO2022)); + + if (! coding->resetter) + coding->resetter = reset_coding_iso_2022; + if (! coding->decoder) + coding->decoder = decode_coding_iso_2022; + if (! coding->encoder) + coding->encoder = encode_coding_iso_2022; + + info->initial_invocation[0] = 0; + info->initial_invocation[1] = -1; + pl = (MPlist *) mplist_get (plist, Minvocation); + if (pl) + { + if (MPLIST_KEY (pl) != Minteger) + MERROR (MERROR_CODING, Mnil); + info->initial_invocation[0] = MPLIST_INTEGER (pl); + if (! MPLIST_TAIL_P (pl)) + { + pl = MPLIST_NEXT (pl); + if (MPLIST_KEY (pl) != Minteger) + MERROR (MERROR_CODING, Mnil); + info->initial_invocation[1] = MPLIST_INTEGER (pl); + } + } + memset (info->designations, 0, sizeof (info->designations)); + for (i = 0, pl = (MPlist *) mplist_get (plist, Mdesignation); + i < 32 && pl && MPLIST_KEY (pl) == Minteger; + i++, pl = MPLIST_NEXT (pl)) + info->designations[i] = MPLIST_INTEGER (pl); + + info->flags = 0; + MPLIST_DO (pl, (MPlist *) mplist_get (plist, Mflags)) + { + MSymbol val; + + if (MPLIST_KEY (pl) != Msymbol) + MERROR (MERROR_CODING, Mnil); + val = MPLIST_SYMBOL (pl); + if (val == Mreset_at_eol) + info->flags |= MCODING_ISO_RESET_AT_EOL; + else if (val == Mreset_at_cntl) + info->flags |= MCODING_ISO_RESET_AT_CNTL; + else if (val == Meight_bit) + info->flags |= MCODING_ISO_EIGHT_BIT; + else if (val == Mlong_form) + info->flags |= MCODING_ISO_LOCKING_SHIFT; + else if (val == Mdesignation_g0) + info->flags |= MCODING_ISO_DESIGNATION_G0; + else if (val == Mdesignation_g1) + info->flags |= MCODING_ISO_DESIGNATION_G1; + else if (val == Mdesignation_ctext) + info->flags |= MCODING_ISO_DESIGNATION_CTEXT; + else if (val == Mdesignation_ctext_ext) + info->flags |= MCODING_ISO_DESIGNATION_CTEXT_EXT; + else if (val == Mlocking_shift) + info->flags |= MCODING_ISO_LOCKING_SHIFT; + else if (val == Msingle_shift) + info->flags |= MCODING_ISO_SINGLE_SHIFT; + else if (val == Msingle_shift_7) + info->flags |= MCODING_ISO_SINGLE_SHIFT_7; + else if (val == Meuc_tw_shift) + info->flags |= MCODING_ISO_EUC_TW_SHIFT; + else if (val == Miso_6429) + info->flags |= MCODING_ISO_ISO6429; + else if (val == Mrevision_number) + info->flags |= MCODING_ISO_REVISION_NUMBER; + else if (val == Mfull_support) + info->flags |= MCODING_ISO_FULL_SUPPORT; + } + + coding->extra_info = info; + } + else + { + if (! coding->decoder || ! coding->encoder) + MERROR (MERROR_CODING, Mnil); + if (! coding->resetter) + coding->ready = 1; + } + + msymbol_put (sym, Mcoding, coding); + msymbol_put (msymbol__canonicalize (sym), Mcoding, coding); + plist = (MPlist *) mplist_get (plist, Maliases); + if (plist) + { + MPLIST_DO (pl, plist) + { + MSymbol alias; + + if (MPLIST_KEY (pl) != Msymbol) + continue; + alias = MPLIST_SYMBOL (pl); + msymbol_put (alias, Mcoding, coding); + msymbol_put (msymbol__canonicalize (alias), Mcoding, coding); + } + } + + MLIST_APPEND1 (&coding_list, codings, coding, MERROR_CODING); + + return sym; +} + +/*=*/ + +/***en + @brief Resolve coding system name. + + The mconv_resolve_coding () function returns $SYMBOL if it + represents a coding system. Otherwise, canonicalize $SYMBOL as to + a coding system name, and if the canonicalized name represents a + coding system, return it. Otherwise, return #Mnil. */ +/***ja + @brief �����ɷϤ�̾�����褹��. + + �ؿ� mconv_resolve_coding () �� $SYMBOL �������ɷϤ򼨤��Ƥ���Ф�����֤��� + �����Ǥʤ���Х����ɷϤ�̾���Ȥ��� $SYMBOL + ���������������줬�����ɷϤ�ɽ���Ƥ�������������� $SYMBOL ���֤��� + �����Ǥʤ����#Mnil ���֤��� */ + + + +MSymbol +mconv_resolve_coding (MSymbol symbol) +{ + MCodingSystem *coding = find_coding (symbol); + + if (! coding) + { + symbol = msymbol__canonicalize (symbol); + coding = find_coding (symbol); + } + return (coding ? coding->name : Mnil); +} + +/*=*/ + + +/***en + @brief List symbols representing coding systems. + + The mconv_list_codings () function makes an array of symbols + representing a coding system, stores the pointer to the array in a + place pointed to by $SYMBOLS, and returns the length of the array. */ +/***ja + @brief �����ɷϤ�ɽ�魯����ܥ����󤹤�. + + �ؿ� mchar_list_codings () �ϡ������ɷϤ򼨤�����ܥ���¤٤�������ꡢ + $SYMBOLS �ǥݥ���Ȥ��줿���ˤ�������ؤΥݥ��󥿤��֤��������Ĺ�����֤��� */ + +int +mconv_list_codings (MSymbol **symbols) +{ + int i = coding_list.used + mplist_length (coding_definition_list); + int j; + MPlist *plist; + + MTABLE_MALLOC ((*symbols), i, MERROR_CODING); + i = 0; + MPLIST_DO (plist, coding_definition_list) + { + MPlist *pl = MPLIST_VAL (plist); + (*symbols)[i++] = MPLIST_SYMBOL (pl); + } + for (j = 0; j < coding_list.used; j++) + if (! mplist_find_by_key (coding_definition_list, + coding_list.codings[j]->name)) + (*symbols)[i++] = coding_list.codings[j]->name; + return i; +} + +/*=*/ + +/***en + @brief Create a code converter bound to a buffer. + + The mconv_buffer_converter () function creates a pointer to a code + converter for coding system $NAME. The code converter is bound + to buffer area of $N bytes pointed to by $BUF. Subsequent + decodings and encodings are done to/from this buffer area. + + $NAME can be #Mnil. In this case, a coding system associated + with the current locale (LC_CTYPE) is used. + + @return + If the operation was successful, mconv_buffer_converter () returns + the created code converter. Otherwise it returns @c NULL and + assigns an error code to the external variable #merror_code. */ + +/***ja + @brief �Хåե��˷���դ���줿�����ɥ���С�������. + + �ؿ� mconv_buffer_converter () �ϡ������ɷ� $NAME + �ѤΥ����ɥ���С������롣���Υ����ɥ���С����ϡ�$BUF �Ǽ�������礭�� $N + �Х��ȤΥХåե��ΰ�˷���դ����롣 + ����ʹߤΥǥ����ɤ���ӥ��󥳡��ɤϡ����ΥХåե��ΰ���Ф��ƹԤʤ��롣 + + $NAME �� #Mnil �Ǥ��äƤ�褤�����ξ��ϸ��ߤΥ������� + (LC_CTYPE) �˴�Ϣ�դ���줿�����ɷϤ��Ȥ��롣 + + @return + �⤷��������������� mconv_buffer_converter () �� �������������ɥ���С������֤��� + �����Ǥʤ���� @c NULL ���֤��������ѿ� #merror_code + �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mconverter} @endlatexonly */ + +/*** + @errors + @c MERROR_SYMBOL, @c MERROR_CODING + + @seealso + mconv_stream_converter () */ + +MConverter * +mconv_buffer_converter (MSymbol name, const unsigned char *buf, int n) +{ + MCodingSystem *coding; + MConverter *converter; + MConverterStatus *internal; + + if (name == Mnil) + name = mlocale_get_prop (mlocale__ctype, Mcoding); + coding = find_coding (name); + if (! coding) + MERROR (MERROR_CODING, NULL); + MSTRUCT_CALLOC (converter, MERROR_CODING); + MSTRUCT_CALLOC (internal, MERROR_CODING); + converter->internal_info = internal; + internal->coding = coding; + if (coding->resetter + && (*coding->resetter) (converter) < 0) + { + free (internal); + free (converter); + MERROR (MERROR_CODING, NULL); + } + + internal->unread = mtext (); + internal->work_mt = mtext (); + mtext__enlarge (internal->work_mt, MAX_UTF8_CHAR_BYTES); + internal->buf.in = buf; + internal->used = 0; + internal->bufsize = n; + internal->binding = BINDING_BUFFER; + + return converter; +} + +/*=*/ + +/***en + @brief Create a code converter bound to a stream. + + The mconv_stream_converter () function creates a pointer to a code + converter for coding system $NAME. The code converter is bound + to stream $FP. Subsequent decodings and encodings are done + to/from this stream. + + $NAME can be #Mnil. In this case, a coding system associated + with the current locale (LC_CTYPE) is used. + + @return + If the operation was successful, mconv_stream_converter () + returns the created code converter. Otherwise it returns @c NULL + and assigns an error code to the external variable + #merror_code. */ + +/***ja + @brief ���ȥ꡼��˷���դ���줿�����ɥ���С�������. + + �ؿ� mconv_stream_converter () �ϡ������ɷ� $NAME + �ѤΥ����ɥ���С������롣���Υ����ɥ���С����ϡ����ȥ꡼�� $FP + �˷���դ����롣 + ����ʹߤΥǥ����ɤ���ӥ��󥳡��ɤϡ����Υ��ȥ꡼����Ф��ƹԤʤ��롣 + + $NAME �� #Mnil �Ǥ��äƤ�褤�����ξ��ϸ��ߤΥ������� + (LC_CTYPE) �˴�Ϣ�դ���줿�����ɷϤ��Ȥ��롣 + + @return + �⤷��������������С�mconv_stream_converter () + �Ϻ������������ɥ���С������֤��������Ǥʤ���� @c NULL + ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mconverter} @endlatexonly */ + +/*** + @errors + @c MERROR_SYMBOL, @c MERROR_CODING + + @seealso + mconv_buffer_converter () */ + +MConverter * +mconv_stream_converter (MSymbol name, FILE *fp) +{ + MCodingSystem *coding; + MConverter *converter; + MConverterStatus *internal; + + if (name == Mnil) + name = mlocale_get_prop (mlocale__ctype, Mcoding); + coding = find_coding (name); + if (! coding) + MERROR (MERROR_CODING, NULL); + MSTRUCT_CALLOC (converter, MERROR_CODING); + MSTRUCT_CALLOC (internal, MERROR_CODING); + converter->internal_info = internal; + internal->coding = coding; + if (coding->resetter + && (*coding->resetter) (converter) < 0) + { + free (internal); + free (converter); + MERROR (MERROR_CODING, NULL); + } + + if (fseek (fp, 0, SEEK_CUR) < 0) + { + if (errno == EBADF) + { + free (internal); + free (converter); + return NULL; + } + internal->seekable = 0; + } + else + internal->seekable = 1; + internal->unread = mtext (); + internal->work_mt = mtext (); + mtext__enlarge (internal->work_mt, MAX_UTF8_CHAR_BYTES); + internal->fp = fp; + internal->binding = BINDING_STREAM; + + return converter; +} + +/*=*/ + +/***en + @brief Reset a code converter. + + The mconv_reset_converter () function resets code converter + $CONVERTER to the initial state. + + @return + If $CONVERTER->coding has its own reseter function, + mconv_reset_converter () returns the result of that function + applied to $CONVERTER. Otherwise it returns 0. */ + +/***ja + @brief �����ɥ���С�����ꥻ�åȤ���. + + �ؿ� mconv_reset_converter () �ϥ����ɥ���С��� $CONVERTER + �������֤��᤹�� + + @return + �⤷ $CONVERTER->coding �˥ꥻ�å��Ѥδؿ����������Ƥ���ʤ�С� + mconv_reset_converter () �Ϥ��δؿ��� $CONVERTER + ��Ŭ�Ѥ�����̤��֤��������Ǥʤ����0���֤��� */ + +int +mconv_reset_converter (MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + + converter->nchars = converter->nbytes = 0; + converter->result = MCONVERSION_RESULT_SUCCESS; + internal->carryover_bytes = 0; + internal->used = 0; + mtext_reset (internal->unread); + if (internal->coding->resetter) + return (*internal->coding->resetter) (converter); + return 0; +} + +/*=*/ + +/***en + @brief Free a code converter. + + The mconv_free_converter () function frees the code converter + $CONVERTER. */ + +/***ja + @brief �����ɥ���С������������. + + �ؿ� mconv_free_converter () �ϥ����ɥ���С��� $CONVERTER + ��������롣 */ + +void +mconv_free_converter (MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + + M17N_OBJECT_UNREF (internal->work_mt); + M17N_OBJECT_UNREF (internal->unread); + free (internal); + free (converter); +} + +/*=*/ + +/***en + @brief Bind a buffer to a code converter. + + The mconv_rebind_buffer () function binds buffer area of $N bytes + pointed to by $BUF to code converter $CONVERTER. Subsequent + decodings and encodings are done to/from this newly bound buffer + area. + + @return + This function always returns $CONVERTER. */ + +/***ja + @brief �����ɥ���С����˥Хåե��ΰ�����դ���. + + �ؿ� mconv_rebind_buffer () �ϡ�$BUF �ˤ�äƻؤ��줿�礭�� $N + �Х��ȤΥХåե��ΰ�򥳡��ɥ���С��� $CONVERTER �˷���դ��롣 + ����ʹߤΥǥ����ɤ���ӥ��󥳡��ɤϡ����ο����˷���դ���줿�Хåե��ΰ���Ф��ƹԤʤ���褦�ˤʤ롣 + + @return + ���δؿ��Ͼ�� $CONVERTER ���֤��� + + @latexonly \IPAlabel{mconv_rebind_buffer} @endlatexonly */ + +/*** + @seealso + mconv_rebind_stream () */ + +MConverter * +mconv_rebind_buffer (MConverter *converter, const unsigned char *buf, int n) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + + internal->buf.in = buf; + internal->used = 0; + internal->bufsize = n; + internal->binding = BINDING_BUFFER; + return converter; +} + +/*=*/ + +/***en + @brief Bind a stream to a code converter. + + The mconv_rebind_stream () function binds stream $FP to code + converter $CONVERTER. Following decodings and encodings are done + to/from this newly bound stream. + + @return + This function always returns $CONVERTER. */ + +/***ja + @brief �����ɥ���С����˥��ȥ꡼������դ���. + + �ؿ� mconv_rebind_stream () �ϡ����ȥ꡼�� $FP �򥳡��ɥ���С��� + $CONVERTER �˷���դ��롣 + ����ʹߤΥǥ����ɤ���ӥ��󥳡��ɤϡ����ο����˷���դ���줿���ȥ꡼����Ф��ƹԤʤ���褦�ˤʤ롣 + + @return + ���δؿ��Ͼ�� $CONVERTER ���֤��� + + @latexonly \IPAlabel{mconv_rebind_stream} @endlatexonly */ + +/*** + @seealso + mconv_rebind_buffer () */ + +MConverter * +mconv_rebind_stream (MConverter *converter, FILE *fp) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + + if (fseek (fp, 0, SEEK_CUR) < 0) + { + if (errno == EBADF) + return NULL; + internal->seekable = 0; + } + else + internal->seekable = 1; + internal->fp = fp; + internal->binding = BINDING_STREAM; + return converter; +} + +/*=*/ + +/***en + @brief Decode a byte sequence into an M-text. + + The mconv_decode () function decodes a byte sequence and appends + the result at the end of M-text $MT. The source byte sequence is + taken from either the buffer area or the stream that is currently + bound to $CONVERTER. + + @return + If the operation was successful, mconv_decode () returns updated + $MT. Otherwise it returns @c NULL and assigns an error code to + the external variable #merror_code. */ + +/***ja + @brief �Х������ M-text �˥ǥ����ɤ���. + + �ؿ� mconv_decode () �ϡ��Х������ǥ����ɤ��Ƥ��η�̤� M-text + $MT ���������ɲä��롣�ǥ����ɸ��ΥХ�����ϡ�$CONVERTER + �˸��߷���դ����Ƥ���Хåե��ΰ褢�뤤�ϥ��ȥ꡼�फ�����롣 + + @return + �⤷��������������С�mconv_decode () �Ϲ������줿 $MT ���֤��� + �����Ǥʤ���� @c NULL ���֤��������ѿ� #merror_code + �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_IO, @c MERROR_CODING + + @seealso + mconv_rebind_buffer (), mconv_rebind_stream (), + mconv_encode (), mconv_encode_range (), + mconv_decode_buffer (), mconv_decode_stream () */ + +MText * +mconv_decode (MConverter *converter, MText *mt) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + int at_most = converter->at_most > 0 ? converter->at_most : -1; + int n; + + M_CHECK_READONLY (mt, NULL); + + if (mt->format != MTEXT_FORMAT_UTF_8) + mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8); + + if (! mt->data) + mtext__enlarge (mt, MAX_UTF8_CHAR_BYTES); + + converter->nchars = converter->nbytes = 0; + converter->result = MCONVERSION_RESULT_SUCCESS; + + n = mtext_nchars (internal->unread); + if (n > 0) + { + int limit = n; + int i; + + if (at_most > 0 && at_most < limit) + limit = at_most; + + for (i = 0, n -= 1; i < limit; i++, converter->nchars++, n--) + mtext_cat_char (mt, mtext_ref_char (internal->unread, n)); + mtext_del (internal->unread, n + 1, internal->unread->nchars); + if (at_most > 0) + { + if (at_most == limit) + return mt; + converter->at_most -= converter->nchars; + } + } + + if (internal->binding == BINDING_BUFFER) + { + (*internal->coding->decoder) (internal->buf.in + internal->used, + internal->bufsize - internal->used, + mt, converter); + internal->used += converter->nbytes; + } + else if (internal->binding == BINDING_STREAM) + { + unsigned char work[CONVERT_WORKSIZE]; + int last_block = converter->last_block; + int use_fread = at_most < 0 && internal->seekable; + + converter->last_block = 0; + while (1) + { + int nbytes, prev_nbytes; + + if (feof (internal->fp)) + nbytes = 0; + else if (use_fread) + nbytes = fread (work, sizeof (unsigned char), CONVERT_WORKSIZE, + internal->fp); + else + { + int c = getc (internal->fp); + + if (c != EOF) + work[0] = c, nbytes = 1; + else + nbytes = 0; + } + + if (ferror (internal->fp)) + { + converter->result = MCONVERSION_RESULT_IO_ERROR; + break; + } + + if (nbytes == 0) + converter->last_block = last_block; + prev_nbytes = converter->nbytes; + (*internal->coding->decoder) (work, nbytes, mt, converter); + if (converter->nbytes - prev_nbytes < nbytes) + { + if (use_fread) + fseek (internal->fp, converter->nbytes - prev_nbytes - nbytes, + SEEK_CUR); + else + ungetc (work[0], internal->fp); + break; + } + if (nbytes == 0 + || (converter->at_most > 0 + && converter->nchars == converter->at_most)) + break; + } + converter->last_block = last_block; + } + else /* internal->binding == BINDING_NONE */ + MERROR (MERROR_CODING, NULL); + + converter->at_most = at_most; + return ((converter->result == MCONVERSION_RESULT_SUCCESS + || converter->result == MCONVERSION_RESULT_INSUFFICIENT_SRC) + ? mt : NULL); +} + +/*=*/ + +/***en + @brief Decode a buffer area based on a coding system. + + The mconv_decode_buffer () function decodes $N bytes of the buffer + area pointed to by $BUF based on the coding system $NAME. A + temporary code converter for decoding is automatically created + and freed. + + @return + If the operation was successful, mconv_decode_buffer () + returns the resulting M-text. Otherwise it returns @c NULL and + assigns an error code to the external variable #merror_code. */ + +/***ja + @brief �����ɷϤ˴�Ť��ƥХåե��ΰ��ǥ����ɤ���. + + �ؿ� mconv_decode_buffer () �ϡ�$BUF �ˤ�äƻؤ��줿 $N + �Х��ȤΥХåե��ΰ�򡢥����ɷ� $NAME �˴�Ť��ƥǥ����ɤ��롣 + �ǥ����ɤ�ɬ�פʥ����ɥ���С����κ����Ȳ����ϼ�ưŪ�˹Ԥʤ��롣 + + @return + �⤷��������������С�mconv_decode_buffer () ������줿 M-text ���֤��� + �����Ǥʤ���� @c NULL ���֤��������ѿ� #merror_code + �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_IO, @c MERROR_CODING + + @seealso + mconv_decode (), mconv_decode_stream () */ + +MText * +mconv_decode_buffer (MSymbol name, const unsigned char *buf, int n) +{ + MConverter *converter = mconv_buffer_converter (name, buf, n); + MText *mt; + + if (! converter) + return NULL; + mt = mtext (); + if (! mconv_decode (converter, mt)) + { + M17N_OBJECT_UNREF (mt); + mt = NULL; + } + mconv_free_converter (converter); + return mt; +} + +/*=*/ + +/***en + @brief Decode a stream input based on a coding system. + + The mconv_decode_stream () function decodes the entire byte + sequence read in from stream $FP based on the coding system $NAME. + A code converter for decoding is automatically created and freed. + + @return + If the operation was successful, mconv_decode_stream () returns + the resulting M-text. Otherwise it returns @c NULL and assigns an + error code to the external variable #merror_code. */ + +/***ja + @brief �����ɷϤ˴�Ť��ƥ��ȥ꡼�����Ϥ�ǥ����ɤ���. + + �ؿ� mconv_decode_stream () �ϡ����ȥ꡼�� $FP + �����ɤ߹��ޤ��Х��������Τ򡢥����ɷ� $NAME + �˴�Ť��ƥǥ����ɤ��롣�ǥ����ɤ�ɬ�פʥ����ɥ���С����κ����Ȳ����ϼ�ưŪ�˹Ԥʤ��롣 + + @return + �⤷��������������С�mconv_decode_stream () ������줿 M-text + ���֤��������Ǥʤ���� @c NULL ���֤��������ѿ� #merror_code + �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_IO, @c MERROR_CODING + + @seealso + mconv_decode (), mconv_decode_buffer () */ + +MText * +mconv_decode_stream (MSymbol name, FILE *fp) +{ + MConverter *converter = mconv_stream_converter (name, fp); + MText *mt; + + if (! converter) + return NULL; + mt = mtext (); + if (! mconv_decode (converter, mt)) + { + M17N_OBJECT_UNREF (mt); + mt = NULL; + } + mconv_free_converter (converter); + return mt; +} + +/*=*/ + +/***en @brief Encode an M-text into a byte sequence. + + The mconv_encode () function encodes M-text $MT and writes the + resulting byte sequence into the buffer area or the stream that is + currently bound to code converter $CONVERTER. + + @return + If the operation was successful, mconv_encode () returns the + number of written bytes. Otherwise it returns -1 and assigns an + error code to the external variable #merror_code. */ + +/***ja + @brief M-text ��Х�����˥��󥳡��ɤ���. + + �ؿ� mconv_encode () �ϡ�M-text $MT �򥨥󥳡��ɤ��ơ������ɥ���С��� + $CONVERTER �˸��߷���դ����Ƥ���Хåե��ΰ褢�뤤�ϥ��ȥ꡼�������줿�Х������񤭹��ࡣ + + @return + �⤷��������������С�mconv_encode () �Ͻ񤭹��ޤ줿�Х��ȿ����֤��� + �����Ǥʤ���� -1 ���֤��������ѿ� #merror_code + �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_IO, @c MERROR_CODING + + @seealso + mconv_rebind_buffer (), mconv_rebind_stream(), + mconv_decode (), mconv_encode_range () */ + +int +mconv_encode (MConverter *converter, MText *mt) +{ + return mconv_encode_range (converter, mt, 0, mtext_nchars (mt)); +} + +/*=*/ + +/***en + @brief Encode a part of an M-text. + + The mconv_encode_range () function encodes the text between $FROM + (inclusive) and $TO (exclusive) in M-text $MT and writes the + resulting byte sequence into the buffer area or the stream that is + currently bound to code converter $CONVERTER. + + @return + If the operation was successful, mconv_encode_range () returns the + number of written bytes. Otherwise it returns -1 and assigns an + error code to the external variable #merror_code. */ + +/***ja + @brief M-text �ΰ�����Х�����˥��󥳡��ɤ���. + + �ؿ� mconv_encode_range () �ϡ�M-text $MT �� $FROM + ��$FROM ���Τ�ޤ�ˤ��� $TO ��$TO���Τϴޤޤʤ��� + �ޤǤ��ϰϤΥƥ����Ȥ򥨥󥳡��ɤ��ơ������ɥ���С��� + $CONVERTER �˸��߷���դ����Ƥ���Хåե��ΰ褢�뤤�ϥ��ȥ꡼�������줿�Х������񤭹��ࡣ + + @return + �⤷��������������С�mconv_encode_range () + �Ͻ񤭹��ޤ줿�Х��ȿ����֤��������Ǥʤ���� -1 + ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_RANGE, @c MERROR_IO, @c MERROR_CODING + + @seealso + mconv_rebind_buffer (), mconv_rebind_stream(), + mconv_decode (), mconv_encode () */ + +int +mconv_encode_range (MConverter *converter, MText *mt, int from, int to) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + + M_CHECK_POS_X (mt, from, -1); + M_CHECK_POS_X (mt, to, -1); + if (to < from) + to = from; + + if (converter->at_most > 0 && from + converter->at_most < to) + to = from + converter->at_most; + + converter->nchars = converter->nbytes = 0; + converter->result = MCONVERSION_RESULT_SUCCESS; + + mtext_put_prop (mt, from, to, Mcoding, internal->coding->name); + if (internal->binding == BINDING_BUFFER) + { + (*internal->coding->encoder) (mt, from, to, + internal->buf.out + internal->used, + internal->bufsize - internal->used, + converter); + internal->used += converter->nbytes; + } + else if (internal->binding == BINDING_STREAM) + { + unsigned char work[CONVERT_WORKSIZE]; + + while (from < to) + { + int written = 0; + int prev_nbytes = converter->nbytes; + int this_nbytes; + + (*internal->coding->encoder) (mt, from, to, work, + CONVERT_WORKSIZE, converter); + this_nbytes = converter->nbytes - prev_nbytes; + while (written < this_nbytes) + { + int wrtn = fwrite (work + written, sizeof (unsigned char), + this_nbytes - written, internal->fp); + + if (ferror (internal->fp)) + break; + written += wrtn; + } + if (written < this_nbytes) + { + converter->result = MCONVERSION_RESULT_IO_ERROR; + break; + } + from += converter->nchars; + } + } + else /* fail safe */ + MERROR (MERROR_CODING, -1); + + return ((converter->result == MCONVERSION_RESULT_SUCCESS + || converter->result == MCONVERSION_RESULT_INSUFFICIENT_DST) + ? converter->nbytes : -1); +} + +/*=*/ + +/***en + @brief Encode an M-text into a buffer area. + + The mconv_encode_buffer () function encodes M-text $MT based on + coding system $NAME and writes the resulting byte sequence into the + buffer area pointed to by $BUF. At most $N bytes are written. A + temporary code converter for encoding is automatically created + and freed. + + @return + If the operation was successful, mconv_encode_buffer () returns + the number of written bytes. Otherwise it returns -1 and assigns + an error code to the external variable #merror_code. */ + +/***ja + @brief M-text �򥨥󥳡��ɤ��ƥХåե��ΰ�˽񤭹���. + + �ؿ� mconv_encode_buffer () ��M-text $MT �򥳡��ɷ� $NAME + �˴�Ť��ƥ��󥳡��ɤ�������줿�Х������ $BUF �λؤ��Хåե��ΰ�˽񤭹��ࡣ + $N �Ͻ񤭹������Х��ȿ��Ǥ��롣 + ���󥳡��ɤ�ɬ�פʥ����ɥ���С����κ����Ȳ����ϼ�ưŪ�˹Ԥʤ��롣 + + @return + �⤷��������������С�mconv_encode_buffer () �Ͻ񤭹��ޤ줿�Х��ȿ����֤��� + �����Ǥʤ����-1���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_IO, @c MERROR_CODING + + @seealso + mconv_encode (), mconv_encode_stream () */ + +int +mconv_encode_buffer (MSymbol name, MText *mt, unsigned char *buf, int n) +{ + MConverter *converter = mconv_buffer_converter (name, buf, n); + int ret; + + if (! converter) + return -1; + ret = mconv_encode (converter, mt); + mconv_free_converter (converter); + return ret; +} + +/*=*/ + +/***en + @brief Encode an M-text to write to a stream. + + The mconv_encode_stream () function encodes M-text $MT based on + coding system $NAME and writes the resulting byte sequence to + stream $FP. A temporary code converter for encoding is + automatically created and freed. + + @return + If the operation was successful, mconv_encode_stream () returns + the number of written bytes. Otherwise it returns -1 and assigns + an error code to the external variable #merror_code. */ + +/***ja + @brief M-text �򥨥󥳡��ɤ��ƥ��ȥ꡼��˽񤭹���. + + �ؿ� mconv_encode_stream () ��M-text $MT �򥳡��ɷ� $NAME + �˴�Ť��ƥ��󥳡��ɤ�������줿�Х�����򥹥ȥ꡼�� $FP + �˽񤭽Ф������󥳡��ɤ�ɬ�פʥ����ɥ���С����κ����Ȳ����ϼ�ưŪ�˹Ԥʤ��롣 + + @return + �⤷��������������С�mconv_encode_stream () + �Ͻ񤭹��ޤ줿�Х��ȿ����֤��������Ǥʤ���� -1 + ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_IO, @c MERROR_CODING + + @seealso + mconv_encode (), mconv_encode_buffer (), mconv_encode_file () */ + +int +mconv_encode_stream (MSymbol name, MText *mt, FILE *fp) +{ + MConverter *converter = mconv_stream_converter (name, fp); + int ret; + + if (! converter) + return -1; + ret = mconv_encode (converter, mt); + mconv_free_converter (converter); + return ret; +} + +/*=*/ + +/***en + @brief Read a character via a code converter. + + The mconv_getc () function reads one character from the buffer + area or the stream that is currently bound to code converter + $CONVERTER. The decoder of $CONVERTER is used to decode the byte + sequence. The internal status of $CONVERTER is updated + appropriately. + + @return + If the operation was successful, mconv_getc () returns the + character read in. If the input source reaches EOF, it returns @c + EOF without changing the external variable #merror_code. If an + error is detected, it returns @c EOF and assigns an error code to + #merror_code. */ + +/***ja + @brief �����ɥ���С�����ͳ�ǰ�ʸ�����ɤߤ���. + + �ؿ� mconv_getc () �ϡ������ɥ���С��� $CONVERTER + �˸��߷���դ����Ƥ���Хåե��ΰ褢�뤤�ϥ��ȥ꡼�फ��ʸ�������ɤ߹��ࡣ + �Х�����Υǥ����ɤˤ� $CONVERTER �Υǥ��������Ѥ����롣 + $CONVERTER ���������֤�ɬ�פ˱����ƹ�������롣 + + @return + ��������������С�mconv_getc () ���ɤ߹��ޤ줿ʸ�����֤������ϸ��� + EOF ��ã�������ϡ������ѿ� #merror_code ���Ѥ����� @c EOF + ���֤������顼�����Ф��줿���� @c EOF ���֤���#merror_code + �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_CODING + + @seealso + mconv_ungetc (), mconv_putc (), mconv_gets () */ + +int +mconv_getc (MConverter *converter) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + int at_most = converter->at_most; + + mtext_reset (internal->work_mt); + converter->at_most = 1; + mconv_decode (converter, internal->work_mt); + converter->at_most = at_most; + return (converter->nchars == 1 + ? STRING_CHAR (internal->work_mt->data) + : EOF); +} + +/*=*/ + +/***en + @brief Push a character back to a code converter. + + The mconv_ungetc () function pushes character $C back to code + converter $CONVERTER. Any number of characters can be pushed + back. The lastly pushed back character is firstly read by the + subsequent mconv_getc () call. The characters pushed back are + registered only in $CONVERTER; they are not written to the input + source. The internal status of $CONVERTER is updated + appropriately. + + @return + If the operation was successful, mconv_ungetc () returns $C. + Otherwise it returns @c EOF and assigns an error code to the + external variable #merror_code. */ + +/***ja + @brief �����ɥ���С����˰�ʸ���᤹. + + �ؿ� mconv_ungetc () �ϡ������ɥ���С��� $CONVERTER ��ʸ�� $C + �򲡤��᤹���ᤵ���ʸ���������¤Ϥʤ������θ�� mconv_getc () + ��ƤӽФ����ݤˤϡ��Ǹ���ᤵ�줿ʸ�����ǽ���ɤޤ�롣�ᤵ�줿ʸ���� + $CONVERTER ���������ߤ���������Ǥ��ꡢ�ºݤ����ϸ��˽񤭹��ޤ��櫓�ǤϤʤ��� + $CONVERTER ���������֤�ɬ�פ˱����ƹ�������롣 + + @return + ��������������С�mconv_ungetc () �� $C ���֤��������Ǥʤ���� @c + EOF ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_CODING, @c MERROR_CHAR + + @seealso + mconv_getc (), mconv_putc (), mconv_gets () */ + +int +mconv_ungetc (MConverter *converter, int c) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + + M_CHECK_CHAR (c, EOF); + + converter->result = MCONVERSION_RESULT_SUCCESS; + mtext_cat_char (internal->unread, c); + return c; +} + +/*=*/ + +/***en + @brief Write a character via a code converter. + + The mconv_putc () function writes character $C to the buffer area + or the stream that is currently bound to code converter + $CONVERTER. The encoder of $CONVERTER is used to encode the + character. The number of bytes actually written is set to the @c + nbytes member of $CONVERTER. The internal status of $CONVERTER + is updated appropriately. + + @return + If the operation was successful, mconv_putc () returns $C. + If an error is detected, it returns @c EOF and assigns + an error code to the external variable #merror_code. */ + +/***ja + @brief �����ɥ���С������ͳ���ư�ʸ���񤭽Ф�. + + �ؿ� mconv_putc () �ϡ������ɥ���С��� $CONVERTER + �˸��߷���դ����Ƥ���Хåե��ΰ褢�뤤�ϥ��ȥ꡼���ʸ�� $C + ��񤭽Ф���ʸ���Υ��󥳡��ɤˤ� $CONVERTER + �Υ��󥳡������Ѥ����롣�ºݤ˽񤭽Ф��줿�Х��ȿ��ϡ�$CONVERTER �Υ��С� + @c nbytes �˥��åȤ���롣$CONVERTER ���������֤�ɬ�פ˱����ƹ�������롣 + + @return + ��������������С�mconv_putc () �� $C ���֤������顼�����Ф��줿���� + @c EOF ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_CODING, @c MERROR_IO, @c MERROR_CHAR + + @seealso + mconv_getc (), mconv_ungetc (), mconv_gets () */ + +int +mconv_putc (MConverter *converter, int c) +{ + MConverterStatus *internal = (MConverterStatus *) converter->internal_info; + + M_CHECK_CHAR (c, EOF); + mtext_reset (internal->work_mt); + mtext_cat_char (internal->work_mt, c); + if (mconv_encode_range (converter, internal->work_mt, 0, 1) < 0) + return EOF; + return c; +} + +/*=*/ + +/***en + @brief Read a line using a code converter. + + The mconv_gets () function reads one line from the buffer area or + the stream that is currently bound to code converter $CONVERTER. + The decoder of $CONVERTER is used for decoding. The decoded + character sequence is appended at the end of M-text $MT. The + final newline character in the original byte sequence is not + appended. The internal status of $CONVERTER is updated + appropriately. + + @return + If the operation was successful, mconv_gets () returns the + modified $MT. If it encounters EOF without reading a single + character, it returns $MT without changing it. If an error is + detected, it returns @c NULL and assigns an error code to + #merror_code. */ + +/***ja + @brief �����ɥ���С�����Ȥäư���ɤ߹���. + + �ؿ� mconv_gets () �ϡ������ɥ���С��� $CONVERTER + �˸��߷���դ����Ƥ���Хåե��ΰ褢�뤤�ϥ��ȥ꡼�फ�� 1 �Ԥ��ɤ߹��ࡣ + �Х�����Υǥ����ɤˤ� $CONVERTER + �Υǥ��������Ѥ����롣�ǥ����ɤ��줿ʸ����� M-text $MT + ���������ɲä���롣���ΥХ�����ν�ü����ʸ�����ɲä���ʤ��� + $CONVERTER ���������֤�ɬ�פ˱����ƹ�������롣 + + @return + ��������������С�mconv_gets () ���ѹ����줿 $MT + ���֤����⤷1ʸ�����ɤޤ��� EOF �������������ϡ�$MT + ���ѹ������ˤ��Τޤ��֤������顼�����Ф��줿���� @c NULL ���֤��� + #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_CODING + + @seealso + mconv_getc (), mconv_ungetc (), mconv_putc () */ + +MText * +mconv_gets (MConverter *converter, MText *mt) +{ + int c; + + M_CHECK_READONLY (mt, NULL); + if (mt->format != MTEXT_FORMAT_UTF_8) + mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8); + + while (1) + { + c = mconv_getc (converter); + if (c == EOF || c == '\n') + break; + mtext_cat_char (mt, c); + } + if (c == EOF && converter->result != MCONVERSION_RESULT_SUCCESS) + /* mconv_getc () sets #merror_code */ + return NULL; + return mt; +} + +/*=*/ + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/coding.h b/src/coding.h new file mode 100644 index 0000000..141822d --- /dev/null +++ b/src/coding.h @@ -0,0 +1,30 @@ +/* coding.h -- header file for the code conversion module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_CODING_H_ +#define _M17N_CODING_H_ + +extern void mconv__register_charset_coding (MSymbol name); + +extern int mcoding__load_from_database (); + +#endif /* _M17N_CODING_H_ */ diff --git a/src/database.c b/src/database.c new file mode 100644 index 0000000..55e8976 --- /dev/null +++ b/src/database.c @@ -0,0 +1,1539 @@ +/* database.c -- database module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nDatabase + @brief The m17n database and API for it. + + The m17n library acquires various kinds of information + from data in the m17n database on demand. Application + programs can also add/load their original data to/from the m17n + database by setting the variable #mdatabase_dir to an + application-specific directory and storing data in it. Users can + overwrite those data by storing preferable data in the directory + specified by the environment variable "M17NDIR", or if it is not + set, in the directory "~/.m17n.d". + + The m17n database contains multiple heterogeneous data, and each + data is identified by four tags; TAG0, TAG1, TAG2, TAG3. Each tag + must be a symbol. + + TAG0 specifies the type of data stored in the database as below. + + @li + If TAG0 is #Mchar_table, the data is of the @e chartable @e + type and provides information about each character. In this case, + TAG1 specifies the type of the information and must be #Msymbol, + #Minteger, #Mstring, #Mtext, or #Mplist. TAG2 and TAG3 can be any + symbols. + + @li + If TAG0 is #Mcharset, the data is of the @e charset @e type + and provides a decode/encode mapping table for a charset. In this + case, TAG1 must be a symbol representing a charset. TAG2 and TAG3 + can be any symbols. + + @li + If TAG0 is neither #Mchar_table nor #Mcharset, the data is of + the @e plist @e type. See the documentation of the + mdatabase_load () function for the details. + In this case, TAG1, TAG2, and TAG3 can be any symbols. + + The notation \ means a data with those + tags. + + Application programs first calls the mdatabase_find () function to + get a pointer to an object of the type #MDatabase. That object + holds information about the specified data. When it is + successfully returned, the mdatabase_load () function loads the + data. The implementation of the structure #MDatabase is + concealed from application programs. +*/ + +/***ja + @addtogroup m17nDatabase + @brief m17n �ǡ����١����ˤȤ���˴ؤ��� API. + + m17n �饤�֥���ɬ�פ˱�����ưŪ�� @e m17n @e �ǡ����١��� + ��������������롣�ޤ����ץꥱ�������ץ������⡢�ȼ��Υǡ����� + m17n �ǡ����١������ɲä��������ưŪ�˼������뤳�Ȥ��Ǥ��롣 + ���ץꥱ�������ץ�����ब�ȼ��Υǡ������ɲá���������ˤϡ��ѿ� + #mdatabase_dir �ˤ��Υ��ץꥱ��������ͭ�Υǥ��쥯�ȥ�򥻥åȤ��� + ������˥ǡ������Ǽ���롣�桼�������Υǡ����򥪡��С��饤�Ȥ����� + �Ȥ��ϡ��Ķ��ѿ� "M17NDIR" �ǻ��ꤵ���ǥ��쥯�ȥ�ʻ��ꤵ��Ƥ��� + ���Ȥ��� "~/.m17n.d" �Ȥ����ǥ��쥯�ȥ�ˤ��̤Υǡ������֤��� + + m17n + �ǡ����١����ˤ�ʣ����¿�ͤʥǡ������ޤޤ�Ƥ��ꡢ�ƥǡ����� + TAG0, TAG1, TAG2, TAG3�ʤ��٤ƥ���ܥ�ˤΣ��ĤΥ����ˤ�äƼ��̤���롣 + + TAG0 �ˤ�äơ��ǡ����١�����Υǡ����Υ����פϼ��Τ褦�˻��ꤵ��롣 + + @li + TAG0 �� #Mchar_table �Ǥ���ǡ����� @e chartable������ + �ȸƤФ졢��ʸ���˴ؤ��������󶡤��롣���ξ�� + TAG1 �Ͼ���μ������ꤹ�륷��ܥ�Ǥ��ꡢ#Msymbol, #Minteger, #Mstring, + #Mtext, #Mplist �Τ����줫�Ǥ��롣TAG2 �� TAG3 ��Ǥ�դΥ���ܥ�Ǥ褤�� + + @li + TAG0 �� #Mcharset �Ǥ���ǡ����� @e charset������ + �ȸƤФ졢ʸ�����å��ѤΥǥ����ɡ����󥳡��ɥޥåפ��󶡤��롣���ξ�� TAG1 + ��ʸ�����åȤΥ���ܥ�Ǥʤ���Фʤ�ʤ���TAG2 �� TAG3 + ��Ǥ�դΥ���ܥ�Ǥ褤�� + + @li + TAG0 �� #Mchar_table �Ǥ� #Mcharset �Ǥ�ʤ���硢���Υǡ����� @e + plist������ �Ǥ��롣�ܺ٤˴ؤ��Ƥϴؿ� mdatabase_load () + �������򻲾ȤΤ��ȡ����ξ�� TAG1��TAG2��TAG3 ��Ǥ�դΥ���ܥ�Ǥ褤�� + + ����Υ�������ĥǡ����١����� \ + �Ȥ���������ɽ���� + + ���ץꥱ�������ץ������ϡ��ޤ��ؿ� mdatabase_find () + ��Ȥäƥǡ����١����˴ؤ��������ݻ����륪�֥������ȡ�#MDatabase + ���ˤؤΥݥ��󥿤����롣��������������顢 mdatabase_load () + �ˤ�äƼºݤ˥ǡ����١���������ɤ��롣��¤�� #MDatabase + ���Ȥ��ɤ���������Ƥ��뤫�ϡ����ץꥱ�������ץ�����फ��ϸ����ʤ��� + + @latexonly \IPAlabel{database} @endlatexonly +*/ + +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "m17n-core.h" +#include "m17n-misc.h" +#include "internal.h" +#include "mtext.h" +#include "character.h" +#include "database.h" +#include "plist.h" + +/** The file containing a list of databases. */ +#define MDB_DIR "mdb.dir" +/** Length of MDB_DIR. */ +#define MDB_DIR_LEN 7 + +#define MAX_TIME(TIME1, TIME2) ((TIME1) >= (TIME2) ? (TIME1) : (TIME2)) + +#define GEN_PATH(path, dir, dir_len, file, file_len) \ + (dir_len + file_len > PATH_MAX ? 0 \ + : (memcpy (path, dir, dir_len), \ + memcpy (path + dir_len, file, file_len), \ + path[dir_len + file_len] = '\0', 1)) + +static MSymbol Masterisk; +static MSymbol Mversion; + +/** Structure for a data in the m17n database. */ + +struct MDatabase +{ + /** Tags to identify the data. [0] specifies the type of + database. If it is #Mchar_table, the type is @e chartable, if + it is #Mcharset, the type is @e charset, otherwise the type is + @e plist. */ + MSymbol tag[4]; + + void *(*loader) (MSymbol *tags, void *extra_info); + + /** The meaning of the value is dependent on . If + is load_database (), the value is a string of the file name that + contains the data. */ + void *extra_info; +}; + +static MPlist *mdatabase__list; + +static int +read_number (char *buf, int *i) +{ + int idx = *i; + int c = buf[idx++]; + int n; + + if (!c) + return -1; + + while (c && isspace (c)) c = buf[idx++]; + + if (c == '0') + { + if (buf[idx] == 'x') + { + for (idx++, c = 0; (n = hex_mnemonic[(unsigned) buf[idx]]) < 16; + idx++) + c = (c << 4) | n; + *i = idx; + return c; + } + c = 0; + } + else if (c == '\'') + { + c = buf[idx++]; + if (c == '\\') + { + c = buf[idx++]; + n = escape_mnemonic[c]; + if (n != 255) + c = n; + } + while (buf[idx] && buf[idx++] != '\''); + *i = idx; + return c; + } + else if (hex_mnemonic[c] < 10) + c -= '0'; + else + return -1; + + while ((n = hex_mnemonic[(unsigned) buf[idx]]) < 10) + c = (c * 10) + n, idx++; + *i = idx; + return c; +} + + +/** Load a data of type @c chartable from the file FD, and return the + newly created chartable. */ + +static void * +load_chartable (FILE *fp, MSymbol type) +{ + int c, from, to; + char buf[1024]; + void *val; + MCharTable *table; + + if (! fp) + MERROR (MERROR_DB, NULL); + + table = mchartable (type, (type == Msymbol ? (void *) Mnil + : type == Minteger ? (void *) -1 + : NULL)); + + while (! feof (fp)) + { + int i, len; + + for (len = 0; len < 1023 && (c = getc (fp)) != EOF && c != '\n'; len++) + buf[len] = c; + buf[len] = '\0'; + if (hex_mnemonic[(unsigned) buf[0]] >= 10) + /* skip comment/invalid line */ + continue; + i = 0; + from = read_number (buf, &i); + if (buf[i] == '-') + i++, to = read_number (buf, &i); + else + to = from; + if (from < 0 || to < from) + continue; + + while (buf[i] && isspace ((unsigned) buf[i])) i++; + c = buf[i]; + if (!c) + continue; + + if (type == Mstring) + { + /* VAL is a C-string. */ + if (! (val = strdup (buf + i))) + MEMORY_FULL (MERROR_DB); + } + else if (type == Minteger) + { + /* VAL is an integer. */ + int positive = 1; + int n; + + if (c == '-') + i++, positive = -1; + n = read_number (buf, &i); + if (n < 0) + goto label_error; + val = (void *) (n * positive); + } + else if (type == Mtext) + { + /* VAL is an M-text. */ + MText *mt; + if (c == '"') + mt = mtext__from_data (buf + i, len - i - 1, MTEXT_FORMAT_UTF_8, 1); + else + { + mt = mtext (); + while ((c = read_number (buf, &i)) >= 0) + mt = mtext_cat_char (mt, c); + } + val = (void *) mt; + } + else if (type == Msymbol) + { + char *p = buf + i; + + while (*p && ! isspace (*p)) + { + if (*p == '\\' && p[1] != '\0') + { + memmove (p, p + 1, buf + len - (p + 1)); + len--; + } + p++; + } + *p = '\0'; + if (! strcmp (buf + i, "nil")) + val = (void *) Mnil; + else + val = (void *) msymbol (buf + i); + } + else if (type == Mplist) + { + val = (void *) mplist__from_string ((unsigned char *) buf + i, + strlen (buf + i)); + } + else + val = NULL; + + if (from == to) + mchartable_set (table, from, val); + else + mchartable_set_range (table, from, to, val); + } + return table; + + label_error: + M17N_OBJECT_UNREF (table); + MERROR (MERROR_DB, NULL); +} + + +static char * +gen_database_name (char *buf, MSymbol *tags) +{ + int i; + + strcpy (buf, msymbol_name (tags[0])); + for (i = 1; i < 4; i++) + { + strcat (buf, ","); + strcat (buf, msymbol_name (tags[i])); + } + return buf; +} + +/* Return the absolute file name for DB_INFO->filename or NULL if no + absolute file name was found. If BUF is non-NULL, store the result + of `stat' call in it. In that case, set *RESULT to the return + value of `stat'. */ + +char * +get_database_file (MDatabaseInfo *db_info, struct stat *buf, int *result) +{ + if (db_info->absolute_filename) + { + if (buf) + *result = stat (db_info->absolute_filename, buf); + } + else + { + struct stat stat_buf; + struct stat *statbuf = buf ? buf : &stat_buf; + int res; + MPlist *plist; + char path[PATH_MAX + 1]; + + MPLIST_DO (plist, mdatabase__dir_list) + { + MDatabaseInfo *dir_info = MPLIST_VAL (plist); + + if (dir_info->status != MDB_STATUS_DISABLED + && GEN_PATH (path, dir_info->filename, dir_info->len, + db_info->filename, db_info->len) + && (res = stat (path, statbuf)) == 0) + { + db_info->absolute_filename = strdup (path); + if (result) + *result = res; + break; + } + } + } + + return db_info->absolute_filename; +} + +static void * +load_database (MSymbol *tags, void *extra_info) +{ + MDatabaseInfo *db_info = extra_info; + void *value; + char *filename = get_database_file (db_info, NULL, NULL); + FILE *fp; + int mdebug_flag = MDEBUG_DATABASE; + char buf[256]; + + MDEBUG_PRINT1 (" [DB] <%s>", gen_database_name (buf, tags)); + if (! filename || ! (fp = fopen (filename, "r"))) + { + if (filename) + MDEBUG_PRINT1 (" open fail: %s\n", filename); + else + MDEBUG_PRINT1 (" not found: %s\n", db_info->filename); + MERROR (MERROR_DB, NULL); + } + + MDEBUG_PRINT1 (" from %s\n", filename); + + if (tags[0] == Mchar_table) + value = load_chartable (fp, tags[1]); + else if (tags[0] == Mcharset) + { + if (! mdatabase__load_charset_func) + MERROR (MERROR_DB, NULL); + value = (*mdatabase__load_charset_func) (fp, tags[1]); + } + else + value = mplist__from_file (fp, NULL); + fclose (fp); + + if (! value) + MERROR (MERROR_DB, NULL); + db_info->time = time (NULL); + return value; +} + + +/** Return a newly allocated MDatabaseInfo for DIRNAME. */ + +static MDatabaseInfo * +get_dir_info (char *dirname) +{ + MDatabaseInfo *dir_info; + + MSTRUCT_CALLOC (dir_info, MERROR_DB); + if (dirname) + { + int len = strlen (dirname); + + if (len + MDB_DIR_LEN < PATH_MAX) + { + MTABLE_MALLOC (dir_info->filename, len + 2, MERROR_DB); + memcpy (dir_info->filename, dirname, len + 1); + /* Append PATH_SEPARATOR if DIRNAME doesn't end with it. */ + if (dir_info->filename[len - 1] != PATH_SEPARATOR) + { + dir_info->filename[len] = PATH_SEPARATOR; + dir_info->filename[++len] = '\0'; + } + dir_info->len = len; + dir_info->status = MDB_STATUS_OUTDATED; + } + else + dir_info->status = MDB_STATUS_DISABLED; + } + else + dir_info->status = MDB_STATUS_DISABLED; + return dir_info; +} + +static void register_databases_in_files (MSymbol tags[4], + char *filename, int len); + +static MDatabase * +find_database (MSymbol tags[4]) +{ + MPlist *plist; + int i; + MDatabase *mdb; + + if (! mdatabase__list) + return NULL; + for (i = 0, plist = mdatabase__list; i < 4; i++) + { + MPlist *pl = mplist__assq (plist, tags[i]); + MPlist *p; + + if ((p = mplist__assq (plist, Masterisk))) + { + MDatabaseInfo *db_info; + int j; + + p = MPLIST_PLIST (p); + for (j = i + 1; j < 4; j++) + p = MPLIST_PLIST (MPLIST_NEXT (p)); + mdb = MPLIST_VAL (MPLIST_NEXT (p)); + db_info = mdb->extra_info; + if (db_info->status != MDB_STATUS_DISABLED) + { + register_databases_in_files (mdb->tag, + db_info->filename, db_info->len); + db_info->status = MDB_STATUS_DISABLED; + return find_database (tags); + } + } + if (! pl) + return NULL; + plist = MPLIST_PLIST (pl); + plist = MPLIST_NEXT (plist); + } + mdb = MPLIST_VAL (plist); + return mdb; +} + +static void +free_db_info (MDatabaseInfo *db_info) +{ + free (db_info->filename); + if (db_info->absolute_filename + && db_info->filename != db_info->absolute_filename) + free (db_info->absolute_filename); + M17N_OBJECT_UNREF (db_info->properties); + free (db_info); +} + +static int +check_version (MText *version) +{ + char *verstr = (char *) MTEXT_DATA (version); + char *endp = verstr + mtext_nbytes (version); + int ver[3]; + int i; + + ver[0] = ver[1] = ver[2] = 0; + for (i = 0; verstr < endp; verstr++) + { + if (*verstr == '.') + { + i++; + if (i == 3) + break; + continue; + } + if (! isdigit (*verstr)) + break; + ver[i] = ver[i] * 10 + (*verstr - '0'); + } + return (ver[0] < M17NLIB_MAJOR_VERSION + || (ver[0] == M17NLIB_MAJOR_VERSION + && (ver[1] < M17NLIB_MINOR_VERSION + || (ver[1] == M17NLIB_MINOR_VERSION + && ver[2] <= M17NLIB_PATCH_LEVEL)))); +} + +static MDatabase * +register_database (MSymbol tags[4], + void *(*loader) (MSymbol *, void *), + void *extra_info, enum MDatabaseStatus status, + MPlist *properties) +{ + MDatabase *mdb; + MDatabaseInfo *db_info; + int i; + MPlist *plist; + + if (properties) + { + MPLIST_DO (plist, properties) + if (MPLIST_PLIST_P (plist)) + { + MPlist *p = MPLIST_PLIST (plist); + + if (MPLIST_SYMBOL_P (p) + && MPLIST_SYMBOL (p) == Mversion + && MPLIST_MTEXT_P (MPLIST_NEXT (p))) + { + if (check_version (MPLIST_MTEXT (MPLIST_NEXT (p)))) + break; + return NULL; + } + } + } + + for (i = 0, plist = mdatabase__list; i < 4; i++) + { + MPlist *pl = mplist__assq (plist, tags[i]); + + if (pl) + pl = MPLIST_PLIST (pl); + else + { + pl = mplist (); + mplist_add (pl, Msymbol, tags[i]); + mplist_push (plist, Mplist, pl); + M17N_OBJECT_UNREF (pl); + } + plist = MPLIST_NEXT (pl); + } + + if (MPLIST_TAIL_P (plist)) + { + MSTRUCT_MALLOC (mdb, MERROR_DB); + for (i = 0; i < 4; i++) + mdb->tag[i] = tags[i]; + mdb->loader = loader; + if (loader == load_database) + { + MSTRUCT_CALLOC (db_info, MERROR_DB); + mdb->extra_info = db_info; + } + else + { + db_info = NULL; + mdb->extra_info = extra_info; + } + mplist_push (plist, Mt, mdb); + } + else + { + mdb = MPLIST_VAL (plist); + if (loader == load_database) + db_info = mdb->extra_info; + else + db_info = NULL; + } + + if (db_info) + { + db_info->status = status; + if (! db_info->filename + || strcmp (db_info->filename, (char *) extra_info) != 0) + { + if (db_info->filename) + free (db_info->filename); + if (db_info->absolute_filename + && db_info->filename != db_info->absolute_filename) + free (db_info->absolute_filename); + db_info->filename = strdup ((char *) extra_info); + db_info->len = strlen ((char *) extra_info); + db_info->time = 0; + } + if (db_info->filename[0] == PATH_SEPARATOR) + db_info->absolute_filename = db_info->filename; + else + db_info->absolute_filename = NULL; + M17N_OBJECT_UNREF (db_info->properties); + if (properties) + { + db_info->properties = properties; + M17N_OBJECT_REF (properties); + } + } + + if (mdb->tag[0] == Mchar_table + && mdb->tag[2] != Mnil + && (mdb->tag[1] == Mstring || mdb->tag[1] == Mtext + || mdb->tag[1] == Msymbol || mdb->tag[1] == Minteger + || mdb->tag[1] == Mplist)) + mchar__define_prop (mdb->tag[2], mdb->tag[1], mdb); + return mdb; +} + +static void +register_databases_in_files (MSymbol tags[4], char *filename, int len) +{ + int i, j; + MPlist *load_key = mplist (); + FILE *fp; + MPlist *plist, *pl; + + MPLIST_DO (plist, mdatabase__dir_list) + { + glob_t globbuf; + int headlen; + + if (filename[0] == PATH_SEPARATOR) + { + if (glob (filename, GLOB_NOSORT, NULL, &globbuf)) + break; + headlen = 0; + } + else + { + MDatabaseInfo *d_info = MPLIST_VAL (plist); + char path[PATH_MAX + 1]; + + if (d_info->status == MDB_STATUS_DISABLED) + continue; + if (! GEN_PATH (path, d_info->filename, d_info->len, filename, len)) + continue; + if (glob (path, GLOB_NOSORT, NULL, &globbuf)) + continue; + headlen = d_info->len; + } + + for (i = 0; i < globbuf.gl_pathc; i++) + { + if (! (fp = fopen (globbuf.gl_pathv[i], "r"))) + continue; + pl = mplist__from_file (fp, load_key); + fclose (fp); + if (! pl) + continue; + if (MPLIST_PLIST_P (pl)) + { + MPlist *p; + MSymbol tags2[4]; + + for (j = 0, p = MPLIST_PLIST (pl); j < 4 && MPLIST_SYMBOL_P (p); + j++, p = MPLIST_NEXT (p)) + tags2[j] = MPLIST_SYMBOL (p); + for (; j < 4; j++) + tags2[j] = Mnil; + for (j = 0; j < 4; j++) + if (tags[j] != Masterisk && tags[j] != tags2[j]) + break; + if (j == 4) + register_database (tags2, load_database, + globbuf.gl_pathv[i] + headlen, + MDB_STATUS_AUTO, p); + } + M17N_OBJECT_UNREF (pl); + } + globfree (&globbuf); + if (filename[0] == PATH_SEPARATOR) + break; + } + M17N_OBJECT_UNREF (load_key); +} + +static int +expand_wildcard_database (MPlist *plist) +{ + MDatabase *mdb; + MDatabaseInfo *db_info; + + plist = MPLIST_NEXT (plist); + while (MPLIST_PLIST_P (plist)) + { + plist = MPLIST_PLIST (plist); + plist = MPLIST_NEXT (plist); + } + mdb = MPLIST_VAL (plist); + if (mdb->loader == load_database + && (db_info = mdb->extra_info) + && db_info->status != MDB_STATUS_DISABLED) + { + register_databases_in_files (mdb->tag, db_info->filename, db_info->len); + db_info->status = MDB_STATUS_DISABLED; + return 1; + } + return 0; +} + + +/* Internal API */ + +/** List of database directories. */ +MPlist *mdatabase__dir_list; + +void *(*mdatabase__load_charset_func) (FILE *fp, MSymbol charset_name); + +int +mdatabase__init () +{ + MDatabaseInfo *dir_info; + char *path; + + mdatabase__load_charset_func = NULL; + + Mchar_table = msymbol ("char-table"); + Mcharset = msymbol ("charset"); + Masterisk = msymbol ("*"); + Mversion = msymbol ("version"); + + mdatabase__dir_list = mplist (); + /** The macro M17NDIR specifies a directory where the system-wide + MDB_DIR file exists. */ + mplist_set (mdatabase__dir_list, Mt, get_dir_info (M17NDIR)); + + /* The variable mdatabase_dir specifies a directory where an + application program specific MDB_DIR file exists. */ + if (mdatabase_dir && strlen (mdatabase_dir) > 0) + mplist_push (mdatabase__dir_list, Mt, get_dir_info (mdatabase_dir)); + + /* The environment variable M17NDIR specifies a directory where a + user specific MDB_DIR file exists. */ + path = getenv ("M17NDIR"); + if (path && strlen (path) > 0) + mplist_push (mdatabase__dir_list, Mt, get_dir_info (path)); + else + { + /* If the env var M17NDIR is not set, check "~/.m17n.d". */ + char *home = getenv ("HOME"); + int len; + + if (home + && (len = strlen (home)) + && (path = alloca (len + 9))) + { + strcpy (path, home); + if (path[len - 1] != PATH_SEPARATOR) + path[len++] = PATH_SEPARATOR; + strcpy (path + len, ".m17n.d"); + dir_info = get_dir_info (path); + mplist_push (mdatabase__dir_list, Mt, dir_info); + } + else + mplist_push (mdatabase__dir_list, Mt, get_dir_info (NULL)); + } + + mdatabase__list = mplist (); + mdatabase__update (); + return 0; +} + +void +mdatabase__fini (void) +{ + MPlist *plist, *p0, *p1, *p2, *p3; + + MPLIST_DO (plist, mdatabase__dir_list) + free_db_info (MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (mdatabase__dir_list); + + /* MDATABASE_LIST ::= ((TAG0 (TAG1 (TAG2 (TAG3 t:MDB) ...) ...) ...) ...) */ + MPLIST_DO (plist, mdatabase__list) + { + p0 = MPLIST_PLIST (plist); + /* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 t:MDB) ...) ...) ...) */ + MPLIST_DO (p0, MPLIST_NEXT (p0)) + { + p1 = MPLIST_PLIST (p0); + /* P1 ::= (TAG1 (TAG2 (TAG3 t:MDB) ...) ...) */ + MPLIST_DO (p1, MPLIST_NEXT (p1)) + { + p2 = MPLIST_PLIST (p1); + /* P2 ::= (TAG2 (TAG3 t:MDB) ...) */ + MPLIST_DO (p2, MPLIST_NEXT (p2)) + { + MDatabase *mdb; + + p3 = MPLIST_PLIST (p2); /* P3 ::= (TAG3 t:MDB) */ + p3 = MPLIST_NEXT (p3); + mdb = MPLIST_VAL (p3); + if (mdb->loader == load_database) + free_db_info (mdb->extra_info); + free (mdb); + } + } + } + } + M17N_OBJECT_UNREF (mdatabase__list); +} + +void +mdatabase__update (void) +{ + MPlist *plist, *p0, *p1, *p2, *p3; + char path[PATH_MAX + 1]; + MDatabaseInfo *dir_info; + struct stat statbuf; + int rescan = 0; + + /* Update elements of mdatabase__dir_list. */ + MPLIST_DO (plist, mdatabase__dir_list) + { + dir_info = MPLIST_VAL (plist); + if (dir_info->filename) + { + if (stat (dir_info->filename, &statbuf) == 0 + && (statbuf.st_mode & S_IFDIR)) + { + if (dir_info->time < statbuf.st_mtime) + { + rescan = 1; + dir_info->time = statbuf.st_mtime; + } + if (GEN_PATH (path, dir_info->filename, dir_info->len, + MDB_DIR, MDB_DIR_LEN) + && stat (path, &statbuf) >= 0 + && dir_info->time < statbuf.st_mtime) + { + rescan = 1; + dir_info->time = statbuf.st_mtime; + } + dir_info->status = MDB_STATUS_UPDATED; + } + else + { + if (dir_info->status != MDB_STATUS_DISABLED) + { + rescan = 1; + dir_info->time = 0; + dir_info->status = MDB_STATUS_DISABLED; + } + } + } + } + + if (! rescan) + return; + + /* At first, mark all databases defined automatically from mdb.dir + file(s) as "disabled". */ + MPLIST_DO (plist, mdatabase__list) + { + p0 = MPLIST_PLIST (plist); + /* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 MDB) ...) ...) ...) */ + MPLIST_DO (p0, MPLIST_NEXT (p0)) + { + p1 = MPLIST_PLIST (p0); + MPLIST_DO (p1, MPLIST_NEXT (p1)) + { + p2 = MPLIST_PLIST (p1); + MPLIST_DO (p2, MPLIST_NEXT (p2)) + { + MDatabase *mdb; + MDatabaseInfo *db_info; + + p3 = MPLIST_PLIST (p2); + p3 = MPLIST_NEXT (p3); + mdb = MPLIST_VAL (p3); + db_info = mdb->extra_info; + if (db_info->status == MDB_STATUS_AUTO) + db_info->status = MDB_STATUS_DISABLED; + } + } + } + } + + plist = mplist (); + MPLIST_DO (p0, mdatabase__dir_list) + mplist_push (plist, MPLIST_KEY (p0), MPLIST_VAL (p0)); + + while (! MPLIST_TAIL_P (plist)) + { + MDatabaseInfo *dir_info = mplist_pop (plist); + MPlist *pl, *p; + int i; + FILE *fp; + + if (dir_info->status == MDB_STATUS_DISABLED) + continue; + if (! GEN_PATH (path, dir_info->filename, dir_info->len, + MDB_DIR, MDB_DIR_LEN)) + continue; + if (! (fp = fopen (path, "r"))) + continue; + pl = mplist__from_file (fp, NULL); + fclose (fp); + if (! pl) + continue; + MPLIST_DO (p, pl) + { + MSymbol tags[4]; + MPlist *p1; + MText *mt; + int nbytes; + int with_wildcard = 0; + + if (! MPLIST_PLIST_P (p)) + continue; + for (i = 0, p1 = MPLIST_PLIST (p); i < 4 && MPLIST_SYMBOL_P (p1); + i++, p1 = MPLIST_NEXT (p1)) + with_wildcard |= ((tags[i] = MPLIST_SYMBOL (p1)) == Masterisk); + if (i == 0 + || tags[0] == Masterisk + || ! MPLIST_MTEXT_P (p1)) + continue; + for (; i < 4; i++) + tags[i] = with_wildcard ? Masterisk : Mnil; + mt = MPLIST_MTEXT (p1); + nbytes = mtext_nbytes (mt); + if (nbytes > PATH_MAX) + continue; + memcpy (path, MTEXT_DATA (mt), nbytes); + path[nbytes] = '\0'; + if (with_wildcard) + register_database (tags, load_database, path, + MDB_STATUS_AUTO_WILDCARD, NULL); + else + register_database (tags, load_database, path, + MDB_STATUS_AUTO, p1); + } + M17N_OBJECT_UNREF (pl); + } + M17N_OBJECT_UNREF (plist); +} + +MPlist * +mdatabase__load_for_keys (MDatabase *mdb, MPlist *keys) +{ + int mdebug_flag = MDEBUG_DATABASE; + MDatabaseInfo *db_info; + char *filename; + FILE *fp; + MPlist *plist; + char name[256]; + + if (mdb->loader != load_database + || mdb->tag[0] == Mchar_table + || mdb->tag[0] == Mcharset) + MERROR (MERROR_DB, NULL); + MDEBUG_PRINT1 (" [DB] <%s>.\n", + gen_database_name (name, mdb->tag)); + db_info = mdb->extra_info; + filename = get_database_file (db_info, NULL, NULL); + if (! filename || ! (fp = fopen (filename, "r"))) + MERROR (MERROR_DB, NULL); + plist = mplist__from_file (fp, keys); + fclose (fp); + return plist; +} + + +/* Check if the database MDB should be reloaded or not. It returns: + + 1: The database has not been updated since it was loaded last + time. + + 0: The database has never been loaded or has been updated + since it was loaded last time. + + -1: The database is not loadable at the moment. */ + +int +mdatabase__check (MDatabase *mdb) +{ + MDatabaseInfo *db_info = (MDatabaseInfo *) mdb->extra_info; + struct stat buf; + int result; + + if (db_info->absolute_filename != db_info->filename + || db_info->status == MDB_STATUS_AUTO) + mdatabase__update (); + + if (! get_database_file (db_info, &buf, &result) + || result < 0) + return -1; + if (db_info->time < buf.st_mtime) + return 0; + return 1; +} + +/* Search directories in mdatabase__dir_list for file FILENAME. If + the file exist, return the absolute pathname. If FILENAME is + already absolute, return a copy of it. */ + +char * +mdatabase__find_file (char *filename) +{ + struct stat buf; + int result; + MDatabaseInfo db_info; + + if (filename[0] == PATH_SEPARATOR) + return (stat (filename, &buf) == 0 ? strdup (filename) : NULL); + db_info.filename = filename; + db_info.len = strlen (filename); + db_info.time = 0; + db_info.absolute_filename = NULL; + if (! get_database_file (&db_info, &buf, &result) + || result < 0) + return NULL; + return db_info.absolute_filename; +} + +char * +mdatabase__file (MDatabase *mdb) +{ + MDatabaseInfo *db_info; + + if (mdb->loader != load_database) + return NULL; + db_info = mdb->extra_info; + return get_database_file (db_info, NULL, NULL); +} + +int +mdatabase__lock (MDatabase *mdb) +{ + MDatabaseInfo *db_info; + struct stat buf; + FILE *fp; + int len; + char *file; + + if (mdb->loader != load_database) + return -1; + db_info = mdb->extra_info; + if (db_info->lock_file) + return -1; + file = get_database_file (db_info, NULL, NULL); + if (! file) + return -1; + len = strlen (file); + db_info->uniq_file = malloc (len + 35); + if (! db_info->uniq_file) + return -1; + db_info->lock_file = malloc (len + 5); + if (! db_info->lock_file) + { + free (db_info->uniq_file); + return -1; + } + sprintf (db_info->uniq_file, "%s.%X.%X", db_info->absolute_filename, + (unsigned) time (NULL), (unsigned) getpid ()); + sprintf (db_info->lock_file, "%s.LCK", db_info->absolute_filename); + + fp = fopen (db_info->uniq_file, "w"); + if (! fp) + { + char *str = strdup (db_info->uniq_file); + char *dir = dirname (str); + + if (stat (dir, &buf) == 0 + || mkdir (dir, 0777) < 0 + || ! (fp = fopen (db_info->uniq_file, "w"))) + { + free (db_info->uniq_file); + free (db_info->lock_file); + db_info->lock_file = NULL; + free (str); + return -1; + } + free (str); + } + fclose (fp); + if (link (db_info->uniq_file, db_info->lock_file) < 0 + && (stat (db_info->uniq_file, &buf) < 0 + || buf.st_nlink != 2)) + { + unlink (db_info->uniq_file); + unlink (db_info->lock_file); + free (db_info->uniq_file); + free (db_info->lock_file); + db_info->lock_file = NULL; + return 0; + } + return 1; +} + +int +mdatabase__save (MDatabase *mdb, MPlist *data) +{ + MDatabaseInfo *db_info; + FILE *fp; + char *file; + MText *mt; + int ret; + + if (mdb->loader != load_database) + return -1; + db_info = mdb->extra_info; + if (! db_info->lock_file) + return -1; + file = get_database_file (db_info, NULL, NULL); + if (! file) + return -1; + mt = mtext (); + if (mplist__serialize (mt, data, 1) < 0) + { + M17N_OBJECT_UNREF (mt); + return -1; + } + fp = fopen (db_info->uniq_file, "w"); + if (! fp) + { + M17N_OBJECT_UNREF (mt); + return -1; + } + if (mt->format > MTEXT_FORMAT_UTF_8) + mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8); + fwrite (MTEXT_DATA (mt), 1, mtext_nchars (mt), fp); + fclose (fp); + M17N_OBJECT_UNREF (mt); + if ((ret = rename (db_info->uniq_file, file)) < 0) + unlink (db_info->uniq_file); + free (db_info->uniq_file); + db_info->uniq_file = NULL; + return ret; +} + +int +mdatabase__unlock (MDatabase *mdb) +{ + MDatabaseInfo *db_info; + + if (mdb->loader != load_database) + return -1; + db_info = mdb->extra_info; + if (! db_info->lock_file) + return -1; + unlink (db_info->lock_file); + free (db_info->lock_file); + db_info->lock_file = NULL; + if (db_info->uniq_file) + { + unlink (db_info->uniq_file); + free (db_info->uniq_file); + } + return 0; +} + +MPlist * +mdatabase__props (MDatabase *mdb) +{ + MDatabaseInfo *db_info; + + if (mdb->loader != load_database) + return NULL; + db_info = mdb->extra_info; + return db_info->properties; +} + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/* External API */ + +/*** @addtogroup m17nCharset */ +/*** @{ */ +/*=*/ +/***en + @brief The symbol @c Mcharset. + + Any decoded M-text has a text property whose key is the predefined + symbol @c Mcharset. The name of @c Mcharset is + "charset". */ + +/***ja + @brief ����ܥ� @c Mcharset. + + �ǥ����ɤ��줿 M-text �ϡ������� @c Mcharset + �Ǥ���褦�ʥƥ����ȥץ��ѥƥ�����ġ� + ����ܥ� @c Mcharset �� "charset" �Ȥ���̾������ġ� */ + +MSymbol Mcharset; +/*=*/ +/*** @} */ +/*=*/ + +/*** @addtogroup m17nDatabase */ +/*** @{ */ + +/*=*/ +/***en + @brief Directory for application specific data. + + If an application program wants to provide a data specific to the + program or a data overriding what supplied by the m17n database, + it must set this variable to a name of directory that contains the + data files before it calls the macro M17N_INIT (). The directory + may contain a file "mdb.dir" which contains a list of data + definitions in the format described in @ref mdbDir "mdbDir(5)". + + The default value is NULL. */ +/***ja + @brief ���ץꥱ��������ͭ�Υǡ����ѥǥ��쥯�ȥ�. + + ���ץꥱ�������ץ�����ब�����Υץ�������ͭ�Υǡ����� m17n + �ǡ����١������񤭤���ǡ������󶡤�����ˤϡ��ޥ��� M17N_INIT () + ��Ƥ����ˤ����ѿ���ǡ����ե������ޤ�ǥ��쥯�ȥ�̾�˥��åȤ��ʤ��ƤϤʤ�ʤ����ǥ��쥯�ȥ�ˤ� + "mdb.dir" �ե�����򤪤����Ȥ��Ǥ��롣����"mdb.dir"�ե�����ˤϡ� + @ref mdbDir "mdbDir(5)" ����������Ƥ���ե����ޥåȤǥǡ�������Υꥹ�Ȥ򵭽Ҥ��롣 + + �ǥե���Ȥ��ͤ� NULL �Ǥ��롣 */ + +char *mdatabase_dir; + +/*=*/ +/***en + @brief Look for a data in the database. + + The mdatabase_find () function searches the m17n database for a + data who has tags $TAG0 through $TAG3, and returns a pointer to + the data. If such a data is not found, it returns @c NULL. */ + +/***ja + @brief �ǡ����١�����Υǡ�����õ��. + + �ؿ� mdatabase_find () �ϡ� m17n �������١������ $TAG0 ���� + $TAG3 �ޤǤΥ�������ĥǡ�����õ��������ؤΥݥ��󥿤��֤������Τ褦�ʥǡ������ʤ���� + @c NULL ���֤��� + + @latexonly \IPAlabel{mdatabase_find} @endlatexonly */ + +MDatabase * +mdatabase_find (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3) +{ + MSymbol tags[4]; + + mdatabase__update (); + tags[0] = tag0, tags[1] = tag1, tags[2] = tag2, tags[3] = tag3; + return find_database (tags); +} + +/*=*/ +/***en + @brief Return a data list of the m17n database. + + The mdatabase_list () function searches the m17n database for data + who have tags $TAG0 through $TAG3, and returns their list by a + plist. The value #Mnil in $TAGn means a wild card that matches + any tag. Each element of the plist has key #Mt and value a + pointer to type #MDatabase. */ +/***ja + @brief m17n �ǡ����١����Υǡ����ꥹ�Ȥ��֤�. + + �ؿ� mdatabase_list () �� m17n �ǡ����١����椫�� $TAG0 ����$TAG3 + �ޤǤΥ�������ĥǡ�����õ�������Υꥹ�Ȥ�plist �Ȥ����֤��� $TAGn �� #Mnil + �Ǥ��ä����ˤϡ�Ǥ�դΥ����˥ޥå�����磻��ɥ����ɤȤ��Ƽ�갷���롣�֤���� + plist �γ����Ǥϥ��� �Ȥ��� #Mt ���ͤȤ��� #MDatabase ���ؤΥݥ��󥿤���ġ� */ + +MPlist * +mdatabase_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3) +{ + MPlist *plist = mplist (), *pl = plist; + MPlist *p, *p0, *p1, *p2, *p3; + + mdatabase__update (); + + MPLIST_DO (p, mdatabase__list) + { + p0 = MPLIST_PLIST (p); + /* P0 ::= (TAG0 (TAG1 (TAG2 (TAG3 MDB) ...) ...) ...) */ + if (MPLIST_SYMBOL (p0) == Masterisk + || (tag0 != Mnil && MPLIST_SYMBOL (p0) != tag0)) + continue; + MPLIST_DO (p0, MPLIST_NEXT (p0)) + { + p1 = MPLIST_PLIST (p0); + if (MPLIST_SYMBOL (p1) == Masterisk) + { + if (expand_wildcard_database (p1)) + { + M17N_OBJECT_UNREF (plist); + return mdatabase_list (tag0, tag1, tag2, tag3); + } + continue; + } + if (tag1 != Mnil && MPLIST_SYMBOL (p1) != tag1) + continue; + MPLIST_DO (p1, MPLIST_NEXT (p1)) + { + p2 = MPLIST_PLIST (p1); + if (MPLIST_SYMBOL (p2) == Masterisk) + { + if (expand_wildcard_database (p2)) + { + M17N_OBJECT_UNREF (plist); + return mdatabase_list (tag0, tag1, tag2, tag3); + } + continue; + } + if (tag2 != Mnil && MPLIST_SYMBOL (p2) != tag2) + continue; + MPLIST_DO (p2, MPLIST_NEXT (p2)) + { + p3 = MPLIST_PLIST (p2); + if (MPLIST_SYMBOL (p3) == Masterisk) + { + if (expand_wildcard_database (p3)) + { + M17N_OBJECT_UNREF (plist); + return mdatabase_list (tag0, tag1, tag2, tag3); + } + continue; + } + if (tag3 != Mnil && MPLIST_SYMBOL (p3) != tag3) + continue; + p3 = MPLIST_NEXT (p3); + pl = mplist_add (pl, Mt, MPLIST_VAL (p3)); + } + } + } + } + if (MPLIST_TAIL_P (plist)) + M17N_OBJECT_UNREF (plist); + return plist; +} + +/*=*/ +/***en + @brief Define a data of the m17n database. + + The mdatabase_define () function defines a data that has tags + $TAG0 through $TAG3 and additional information $EXTRA_INFO. + + $LOADER is a pointer to a function that loads the data from the + database. This function is called from the mdatabase_load () + function with the two arguments $TAGS and $EXTRA_INFO. Here, + $TAGS is the array of $TAG0 through $TAG3. + + If $LOADER is @c NULL, the default loader of the m17n library is + used. In this case, $EXTRA_INFO must be a string specifying a + filename that contains the data. + + @return + If the operation was successful, mdatabase_define () returns a + pointer to the defined data, which can be used as an argument to + mdatabase_load (). Otherwise, it returns @c NULL. */ + +/***ja + @brief m17n �ǡ����١����Υǡ������������. + + �ؿ� mdatabase_define () �� $TAG0 ���� $TAG3 �ޤǤΥ���������ղþ��� + $EXTRA_INFO ����ĥǡ�����������롣 + + $LOADER �Ϥ��Υǡ����Υ����ɤ��Ѥ�����ؿ��ؤΥݥ��󥿤Ǥ��롣���δؿ��� + mdatabase_load () ���� $TAGS �� $EXTRA_INFO �Ȥ�����Ĥΰ����դ��ǸƤӽФ���롣������ + $TAGS �� $TAG0 ���� $TAG3 �ޤǤ�����Ǥ��롣 + + �⤷ $LOADER �� @c NULL �ʤ顢m17n �饤�֥��ɸ��Υ��������Ȥ��롣���ξ��ˤ� + $EXTRA_INFO �ϥǡ�����ޤ�ե�����̾�Ǥʤ��ƤϤʤ�ʤ��� + + @return + ��������������� mdatabase_define () + ��������줿�ǡ����١����ؤΥݥ��󥿤��֤������Υݥ��󥿤ϴؿ� mdatabase_load () + �ΰ����Ȥ����Ѥ��뤳�Ȥ��Ǥ��롣�����Ǥʤ���� @c NULL ���֤��� + + @latexonly \IPAlabel{mdatabase_define} @endlatexonly */ + +/*** + @seealso + mdatabase_load (), mdatabase_define () */ + +MDatabase * +mdatabase_define (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3, + void *(*loader) (MSymbol *, void *), + void *extra_info) +{ + MDatabase *mdb; + MSymbol tags[4]; + + tags[0] = tag0, tags[1] = tag1, tags[2] = tag2, tags[3] = tag3; + if (! loader) + loader = load_database; + mdb = register_database (tags, loader, extra_info, MDB_STATUS_EXPLICIT, NULL); + return mdb; +} + +/*=*/ +/***en + @brief Load a data from the database. + + The mdatabase_load () function loads a data specified in $MDB and + returns the contents. The type of contents depends on the type of + the data. + + If the data is of the @e plist @e type, this function returns a + pointer to @e plist. + + If the database is of the @e chartable @e type, it returns a + chartable. The default value of the chartable is set according to + the second tag of the data as below: + + @li If the tag is #Msymbol, the default value is #Mnil. + @li If the tag is #Minteger, the default value is -1. + @li Otherwise, the default value is @c NULL. + + If the data is of the @e charset @e type, it returns a plist of length 2 + (keys are both #Mt). The value of the first element is an array + of integers that maps code points to the corresponding character + codes. The value of the second element is a chartable of integers + that does the reverse mapping. The charset must be defined in + advance. */ + + +/***ja + @brief �ǡ����١�������ǡ���������ɤ���. + + �ؿ� mdatabase_load () �� $MDB + ���ؤ��ǡ���������ɤ���������Ȥ��֤����֤�����Τϥǡ����Υ����פˤ�äưۤʤ롣 + + �ǡ����� @e plist������ �ʤ�С� @e plist �ؤΥݥ��󥿤��֤��� + + �ǡ����� @e chartable������ �ʤ��ʸ���ơ��֥���֤��� + ʸ���ơ��֥�Υǥե�����ͤϡ��ǡ�������2�����ˤ�äưʲ��Τ褦�˷�ޤ롣 + + @li ������ #Msymbol �ʤ顢�ǥե�����ͤ� #Mnil + @li ������ #Minteger �ʤ顢�ǥե�����ͤ� -1 + @li ����ʳ��ʤ顢�ǥե�����ͤ� @c NULL + + �ǡ����� @e charset������ �ʤ��Ĺ�� 2 �� plist ���֤��ʥ����϶���#Mt �ˡ� + �ǽ�����Ǥ��ͤϥ����ɥݥ���Ȥ��б�����ʸ�������ɤ˥ޥåפ�������������Ǥ��롣 + �����ܤ����Ǥ��ͤϵդΥޥåפ򤹤�ʸ���ơ��֥�Ǥ��롣 + ����ʸ�����åȤ�ͽ���������Ƥ��ʤ���Фʤ�ʤ��� + + @latexonly \IPAlabel{mdatabase_load} @endlatexonly + */ + +/*** + @seealso + mdatabase_load (), mdatabase_define () */ + +void * +mdatabase_load (MDatabase *mdb) +{ + return (*mdb->loader) (mdb->tag, mdb->extra_info); +} + +/*=*/ +/***en + @brief Get tags of a data. + + The mdatabase_tag () function returns an array of tags (symbols) + that identify the data in $MDB. The length of the array is + four. */ + +/***ja + @brief �ǡ����Υ���������. + + �ؿ� mdatabase_tag () �ϡ��ǡ��� $MDB �Υ����ʥ���ܥ�ˤ�������֤��������Ĺ���� + 4 �Ǥ��롣 + + @latexonly \IPAlabel{mdatabase_tag} @endlatexonly */ + +MSymbol * +mdatabase_tag (MDatabase *mdb) +{ + return mdb->tag; +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/database.h b/src/database.h new file mode 100644 index 0000000..06fe67b --- /dev/null +++ b/src/database.h @@ -0,0 +1,95 @@ +/* database.h -- header file for the database module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_DATABASE_H_ +#define _M17N_DATABASE_H_ + +#ifndef M17NDIR +#define M17NDIR "/usr/local/share/m17n" +#endif + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +#ifndef PATH_SEPARATOR +#define PATH_SEPARATOR '/' +#endif + +enum MDatabaseStatus + { + /* The database was defined automatically (from mdb.dir file(s)) + with no wildcard tag. */ + MDB_STATUS_AUTO, + /* The database was defined automatically (from mdb.dir file(s)). + with a wildcard tag. */ + MDB_STATUS_AUTO_WILDCARD, + /* The database was defined explicitely (by mdatabase_define ()). */ + MDB_STATUS_EXPLICIT, + /* The databse is currently disabled. (usually because it is + deleted from mdb.dir file(s)). */ + MDB_STATUS_DISABLED, + MDB_STATUS_UPDATED, + MDB_STATUS_OUTDATED + }; + +typedef struct +{ + /* Name of the file containing the database. */ + char *filename; + /* Length of FILENAME. */ + int len; + /* Absolute path of filename. */ + char *absolute_filename; + /* The current status of the database. */ + enum MDatabaseStatus status; + /* When the database was loaded last. 0 if it has never been + loaded. */ + time_t time; + char *lock_file, *uniq_file; + + MPlist *properties; +} MDatabaseInfo; + +extern MPlist *mdatabase__dir_list; + +extern void mdatabase__update (void); + +extern MPlist *mdatabase__load_for_keys (MDatabase *mdb, MPlist *keys); + +extern int mdatabase__check (MDatabase *mdb); + +extern char *mdatabase__find_file (char *filename); + +extern char *mdatabase__file (MDatabase *mdb); + +extern int mdatabase__lock (MDatabase *mdb); + +extern int mdatabase__save (MDatabase *mdb, MPlist *data); + +extern int mdatabase__unlock (MDatabase *mdb); + +extern MPlist *mdatabase__props (MDatabase *mdb); + +extern void *(*mdatabase__load_charset_func) (FILE *fp, MSymbol charset_name); + +#endif /* not _M17N_DATABASE_H_ */ diff --git a/src/draw.c b/src/draw.c new file mode 100644 index 0000000..81b517e --- /dev/null +++ b/src/draw.c @@ -0,0 +1,2955 @@ +/* draw.c -- drawing module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nDraw + @brief Drawing M-texts on a window. + + The m17n GUI API provides functions to draw M-texts. + + The fonts used for drawing are selected automatically based on the + fontset and the properties of a face. A face also specifies the + appearance of M-texts, i.e. font size, color, underline, etc. + + The drawing format of M-texts can be controlled in a variety of + ways, which provides powerful 2-dimensional layout + facility. */ + +/***ja + @addtogroup m17nDraw + @brief M-text �򥦥���ɥ������褹��. + + m17n-gui API �ˤϡ�M-text ��ɽ�����뤿��δؿ����Ѱդ���Ƥ��롣 + + ɽ�����Ѥ�����ե���Ȥϡ��ե���ȥ��åȤ� face + �Υץ��ѥƥ��˴�Ť��Ƽ�ưŪ�˷��ꤵ��롣�ޤ����ե���ȤΥ������俧�䲼���ʤɤθ��ɤ��� + face �ˤ�äƷ�ޤ롣 + + M-text ������ե����ޥåȤ�¿�ͤ���ˡ������Ǥ���Τǡ����Ϥ��󼡸��쥤�����ȵ�ǽ���¸��Ǥ��롣 + */ + +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include +#include +#include + +#include "config.h" +#include "m17n-gui.h" +#include "m17n-misc.h" +#include "internal.h" +#include "symbol.h" +#include "mtext.h" +#include "textprop.h" +#include "internal-gui.h" +#include "internal-flt.h" +#include "face.h" +#include "font.h" + +#ifdef HAVE_FRIBIDI +#include +#endif /* HAVE_FRIBIDI */ + +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#define MIN(x, y) ((x) < (y) ? (x) : (y)) + +static MSymbol M_glyph_string; + +/* Special scripts */ +static MSymbol Mcommon; +/* Special categories */ +static MSymbol McatCc, McatCf; + +static MCharTable *linebreak_table; +static MSymbol M_break_at_space, M_break_at_word, M_break_at_any; +static MSymbol M_kinsoku_bol, M_kinsoku_eol; + + +/* Glyph-string composer. */ + +static MSymbol MbidiR; +static MSymbol MbidiAL; +static MSymbol MbidiRLE; +static MSymbol MbidiRLO; +static MSymbol MbidiBN; +static MSymbol MbidiS; +static MSymbol MbidiNSM; + +static int +analyse_bidi_level (MGlyphString *gstring) +{ + int len = gstring->used - 2; + int bidi_sensitive = gstring->control.orientation_reversed; + int max_level; + MGlyph *g; + int i; +#ifdef HAVE_FRIBIDI + FriBidiParType base = bidi_sensitive ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR; + FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len); + FriBidiLevel *levels; + FriBidiStrIndex *indices; +#else /* not HAVE_FRIBIDI */ + int *logical = alloca (sizeof (int) * len); + char *levels = alloca (len); + + memset (levels, 0, sizeof (int) * len); +#endif /* not HAVE_FRIBIDI */ + + for (g = MGLYPH (1), i = 0; g->type != GLYPH_ANCHOR; g++, i++) + { + if (! bidi_sensitive +#ifndef HAVE_FRIBIDI + || 1 +#endif /* not HAVE_FRIBIDI */ + ) + { + MSymbol bidi = (MSymbol) mchar_get_prop (g->g.c, Mbidi_category); + + if (bidi == MbidiR || bidi == MbidiAL + || bidi == MbidiRLE || bidi == MbidiRLO) + { + bidi_sensitive = 1; +#ifndef HAVE_FRIBIDI + levels[i] = 1; +#endif /* not HAVE_FRIBIDI */ + } +#ifndef HAVE_FRIBIDI + else if (bidi == MbidiNSM && i > 0 && levels[i - 1]) + levels[i] = 1; +#endif /* not HAVE_FRIBIDI */ + } + logical[i] = g->g.c; + } + + if (! bidi_sensitive) + return 0; + +#ifdef HAVE_FRIBIDI + levels = alloca (sizeof (FriBidiLevel) * (len + 1)); + indices = alloca (sizeof (FriBidiStrIndex) * (len + 1)); + + fribidi_log2vis (logical, len, &base, NULL, NULL, indices, levels); +#endif /* not HAVE_FRIBIDI */ + + MGLYPH (0)->bidi_level = 0; + max_level = 0; + for (g = MGLYPH (1), i = 0; i < len; g++, i++) + { + g->bidi_level = levels[i]; + if (max_level < g->bidi_level) + max_level = g->bidi_level; + } + MGLYPH (i)->bidi_level = 0; + return max_level; +} + +static void +visual_order (MGlyphString *gstring) +{ + MGlyph *glyphs = alloca (sizeof (MGlyph) * gstring->used); + int i, j, gidx; + + memcpy (glyphs, gstring->glyphs, sizeof (MGlyph) * gstring->used); + + for (i = gidx = 0; i < gstring->used - 1; gidx++) + { + int level = glyphs[i].bidi_level; + + gstring->glyphs[gidx] = glyphs[i]; + glyphs[i].rface = NULL; + + if (level % 2) + { + int prev_level = glyphs[i - 1].bidi_level; + + if (prev_level == level) + i--; + else if (prev_level > level) + { + for (; glyphs[i - 1].bidi_level > level; i--); + if (glyphs[i].bidi_level % 2) + for (level = glyphs[i].bidi_level; + glyphs[i + 1].bidi_level == level; i++); + } + else + for (i++; ! glyphs[i].rface; i++); + } + else + { + int next_level = glyphs[i + 1].bidi_level; + + if (next_level == level) + i++; + else if (next_level > level) + { + for (; glyphs[i + 1].bidi_level > level; i++); + if ((glyphs[i].bidi_level % 2) == 0) + for (level = glyphs[i].bidi_level; + glyphs[i - 1].bidi_level == level; i--); + } + else + { + int save = i + 1; + + for (i--; glyphs[i].bidi_level >= level; i--); + if (! glyphs[i].rface) + for (i = save; ! glyphs[i].rface; i++); + } + } + } + for (i = 1; i < gstring->used - 1; i++) + { + MGlyph *g = gstring->glyphs + i; + int level = g->bidi_level; + + for (j = i; g->g.from == gstring->glyphs[j + 1].g.from; j++); + if ((level % 2) && j > i) + { + memcpy (glyphs + i, gstring->glyphs + i, + sizeof (MGlyph) * (j - i + 1)); + for (; i <= j; i++) + g[j - i] = glyphs[i]; + i--; + } + } +} + +static MSymbol +font_id (MFLTFont *font) +{ + return ((MFLTFontForRealized *) font)->rfont->id; +} + +static int +run_flt (MGlyphString *gstring, int from, int to, MRealizedFace *rface) +{ + MRealizedFont *rfont = rface->rfont; + MSymbol layouter = rface->layouter; + MFLTGlyphString flt_gstr; + MFLTFontForRealized font; + MFLT *flt; + int from_pos = MGLYPH (from)->g.from; + int len = to - from; + int catcode; + int i; + + flt = mflt_get (layouter); + flt_gstr.glyph_size = sizeof (MGlyph); + flt_gstr.glyphs = (MFLTGlyph *) (gstring->glyphs); + flt_gstr.used = gstring->used; + flt_gstr.allocated = gstring->size; + flt_gstr.r2l = 0; + font.font.family = mfont_get_prop (rfont->font, Mfamily); + font.font.x_ppem = rfont->x_ppem; + font.font.y_ppem = rfont->y_ppem; + font.font.get_glyph_id = mfont__get_glyph_id; + font.font.get_metrics = mfont__get_metrics; + font.font.check_otf = rfont->driver->check_otf; + font.font.drive_otf = rfont->driver->drive_otf; + font.font.internal = NULL; + font.rfont = rfont; + mflt_font_id = font_id; + mflt_iterate_otf_feature = rfont->driver->iterate_otf_feature; + mflt_try_otf = rfont->driver->try_otf; + for (i = 0; i < 3; i++) + { + to = mflt_run (&flt_gstr, from, to, &font.font, flt); + if (to != -2) + break; + APPEND_GLYPH (gstring, *MGLYPH (0)); + APPEND_GLYPH (gstring, *MGLYPH (0)); + gstring->used -= 2; + } + if (from + len != to) + gstring->used += to - (from + len); + for (i = from, catcode = -1; i < to; i++) + { + MGlyph *g = MGLYPH (i); + + g->g.from += from_pos - from; + g->g.to += from_pos - from + 1; + g->g.xadv >>= 6; + g->g.yadv >>= 6; + g->g.ascent >>= 6; + g->g.descent >>= 6; + g->g.lbearing >>= 6; + g->g.rbearing >>= 6; + g->g.xoff >>= 6; + g->g.yoff >>= 6; + g->rface = rface; + if (catcode < 0 || g->g.from != g[-1].g.from) + { + MSymbol category = mchar_get_prop (g->g.c, Mcategory); + + catcode = (category == McatCf + ? GLYPH_CATEGORY_FORMATTER + : category != Mnil && MSYMBOL_NAME (category)[0] == 'M' + ? GLYPH_CATEGORY_MODIFIER + : GLYPH_CATEGORY_NORMAL); + } + g->category = catcode; + } + return to; +} + +/** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for + displaying them on FRAME. + + This function fills these members: + pos, to, c, code, rface, bidi_level, categories, type, combining_code + The other members are filled by layout_glyph_string. */ + +static void +compose_glyph_string (MFrame *frame, MText *mt, int from, int to, + MGlyphString *gstring) +{ + MRealizedFace *default_rface = frame->rface; + int stop, face_change, language_change, charset_change, font_change; + MGlyph g_tmp, *g, *last_g; + int pos; + MSymbol language = Mnil, script = Mnil, charset = Mnil; + MSymbol non_latin_script = Mnil; + MRealizedFace *rface = default_rface; + MRealizedFont *rfont; + int size = gstring->control.fixed_width; + int max_bidi_level = 0; + int i; + + MLIST_RESET (gstring); + gstring->from = from; + + /* At first generate glyphs with , , , , + and members.*/ + INIT_GLYPH (g_tmp); + + /** Put anchor glyphs at the head and tail. */ + g_tmp.type = GLYPH_ANCHOR; + g_tmp.g.from = g_tmp.g.to = from; + APPEND_GLYPH (gstring, g_tmp); + stop = face_change = font_change = pos = from; + while (1) + { + int c; + MSymbol category; + + if (pos == stop) + { + if (pos == to) + break; + if (pos < mtext_nchars (mt)) + { + MFont *font = rface->font; + MFace *faces[64]; + int num; + + if (pos == font_change) + { + font = mtext_get_prop (mt, pos, Mfont); + mtext_prop_range (mt, Mfont, pos, NULL, &font_change, 0); + if (font_change == mtext_nchars (mt)) + font_change++; + } + if (pos == face_change) + { + num = mtext_get_prop_values (mt, pos, Mface, + (void **) faces, 64); + mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1); + if (face_change == mtext_nchars (mt)) + face_change++; + } + else + { + faces[0] = &rface->face; + num = 1; + } + rface = mface__realize (frame, faces, num, size, font); + } + else + rface = default_rface; + stop = to; + if (stop > font_change) + stop = font_change; + if (stop > face_change) + stop = face_change; + } + + if (pos < mtext_nchars (mt)) + c = mtext_ref_char (mt, pos); + else + c = '\n'; + g_tmp.type + = (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR; + g_tmp.g.c = c; + g_tmp.g.from = pos++; + g_tmp.g.to = pos; + g_tmp.rface = rface; + category = mchar_get_prop (c, Mcategory); + if (category == McatCf) + g_tmp.category = GLYPH_CATEGORY_FORMATTER; + else if (category != Mnil && MSYMBOL_NAME (category)[0] == 'M') + g_tmp.category = GLYPH_CATEGORY_MODIFIER; + else + g_tmp.category = GLYPH_CATEGORY_NORMAL; + + if ((c <= ' ' || c == 127) && g_tmp.type == GLYPH_CHAR) + { + MGlyph ctrl[2]; + + ctrl[0] = ctrl[1] = g_tmp; + ctrl[0].g.c = '^'; + ctrl[1].g.c = c < ' ' ? c + 0x40 : '?'; + APPEND_GLYPH (gstring, ctrl[0]); + APPEND_GLYPH (gstring, ctrl[1]); + } + else + APPEND_GLYPH (gstring, g_tmp); + if (c == '\n' && gstring->control.two_dimensional) + break; + } + /* Append an anchor glyph. */ + INIT_GLYPH (g_tmp); + g_tmp.type = GLYPH_ANCHOR; + g_tmp.g.from = g_tmp.g.to = pos; + APPEND_GLYPH (gstring, g_tmp); + gstring->to = pos; + + if (gstring->control.enable_bidi) + max_bidi_level = analyse_bidi_level (gstring); + + /* The next loop is to change each member for non-ASCII + characters if necessary. */ + stop = charset_change = language_change = from; + rfont = default_rface->rfont; + for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++) + { + int c = g->g.c; + MSymbol this_script; + + if (c < 0x100) + /* Short cut for the obvious case. */ + this_script = Mlatin; + else + { + this_script = (MSymbol) mchar_get_prop (c, Mscript); + if (this_script == Minherited || this_script == Mcommon) + { + if (g > MGLYPH (1)) + { + MSymbol category = mchar_get_prop (g[-1].g.c, Mcategory); + + if (category != Mnil && MSYMBOL_NAME (category)[0] != 'Z') + this_script = script; + } + } + if (this_script == Mcommon && non_latin_script) + this_script = non_latin_script; + if (this_script == Mcommon) + { + /* Search forward for a character that explicitly + specifies a non-latin script. */ + MSymbol sym; + MGlyph *g1; + + for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++) + if (g1->g.c >= 0x100 + && (sym = mchar_get_prop (g1->g.c, Mscript)) != Mcommon + && sym != Minherited) + { + this_script = sym; + break; + } + } + if (this_script == Minherited || this_script == Mcommon) + this_script = (MSymbol) mchar_get_prop (c, Mblock); + } + + pos = g->g.from; + if (pos == stop || script != this_script || g->rface->rfont != rfont) + { + while (last_g < g) + last_g = mface__for_chars (script, language, charset, + last_g, g, size); + script = this_script; + if (script != Mnil && script != Mlatin) + non_latin_script = script; + rfont = g->rface->ascii_rface->rfont; + if (pos == stop) + { + if (pos < mtext_nchars (mt) && pos == language_change) + { + language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage); + mtext_prop_range (mt, Mlanguage, pos, NULL, + &language_change, 0); + } + if (pos < mtext_nchars (mt) && pos == charset_change) + { + charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset); + mtext_prop_range (mt, Mcharset, pos, NULL, + &charset_change, 0); + } + stop = to; + if (stop > language_change) + stop = language_change; + if (stop > charset_change) + stop = charset_change; + } + } + } + while (last_g < g) + last_g = mface__for_chars (script, language, charset, last_g, g, size); + + /* The next loop is to run FLT or perform the default combining if + necessary. */ + for (i = 1, g = MGLYPH (1); g->type != GLYPH_ANCHOR;) + { + MGlyph *this = g; + + if (this->type == GLYPH_CHAR && this->rface->rfont) + { + int start = i++; + + if (this->rface->layouter != Mnil) + { + MGlyph *prev = MGLYPH (start - 1); + + while (prev->type == GLYPH_CHAR + && prev->category == GLYPH_CATEGORY_FORMATTER + && (mfont__encode_char (NULL, (MFont *) this->rface->rfont, + NULL, prev->g.c) + != MCHAR_INVALID_CODE)) + { + prev->rface->rfont = this->rface->rfont; + start--, prev--; + } + + for (g++; + (g->type == GLYPH_CHAR + && g->rface->layouter == this->rface->layouter + && (g->rface->rfont == this->rface->rfont + || (g->category == GLYPH_CATEGORY_FORMATTER + && (mfont__encode_char (NULL, + (MFont *) this->rface->rfont, + NULL, g->g.c) + != MCHAR_INVALID_CODE)))); + i++, g++) + g->rface->rfont = this->rface->rfont; + i = run_flt (gstring, start, i, this->rface); + } + else + { + g++; + while (g->type == GLYPH_CHAR + && g->g.c >= 0x100 + && g->category == GLYPH_CATEGORY_MODIFIER + && g->rface->rfont + && g->rface->layouter == Mnil) + i++, g++; + if (start + 1 < i) + { + this->rface->layouter = Mcombining; + run_flt (gstring, start, i, this->rface); + } + else + mfont__get_metric (gstring, start, i); + } + g = MGLYPH (i); + } + else + i++, g++; + } + + /* At last, reorder glyphs visually if necessary. */ + if (max_bidi_level > 0) + visual_order (gstring); +} + +typedef struct { + int width, lbearing, rbearing; +} MSubTextExtents; + +static void +layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to, + MSubTextExtents *extents) +{ + int g_physical_ascent, g_physical_descent; + MGlyph *g = MGLYPH (from); + MGlyph *last_g = MGLYPH (to); + + g_physical_ascent = gstring->physical_ascent; + g_physical_descent = gstring->physical_descent; + extents->width = extents->lbearing = extents->rbearing = 0; + + for (g = MGLYPH (from); g < last_g; g++) + { + g_physical_ascent = MAX (g_physical_ascent, g->g.ascent); + g_physical_descent = MAX (g_physical_descent, g->g.descent); + extents->lbearing = MIN (extents->lbearing, + extents->width + g->g.lbearing); + extents->rbearing = MAX (extents->rbearing, + extents->width + g->g.rbearing); + extents->width += g->g.xadv; + } + + gstring->physical_ascent = g_physical_ascent; + gstring->physical_descent = g_physical_descent; +} + + +/** Decide the layout of glyphs in GSTRING. Space glyphs are handled + by this function directly. Character glyphs are handled by + layouter functions registered in font drivers. + + This function fill-in all the remaining members of glyphs. */ + +static void +layout_glyph_string (MFrame *frame, MGlyphString *gstring) +{ + /* Default width of TAB. */ + int tab_width = frame->space_width * (gstring->control.tab_width + ? gstring->control.tab_width : 8); + int tab_found = 0; + MGlyph *g; + MGlyph pad; + MDrawControl *control = &(gstring->control); + int width; + MFaceBoxProp *box; + int box_line_height = 0; + int ignore_formatting_char = control->ignore_formatting_char; + + gstring->ascent = gstring->descent = 0; + gstring->physical_ascent = gstring->physical_descent = 0; + gstring->width = gstring->lbearing = gstring->rbearing = 0; + + g = MGLYPH (1); + box = NULL; + while (g->type != GLYPH_ANCHOR) + { + if (box != g->rface->box) + { + int gidx = GLYPH_INDEX (g); + + if (box) + { + /* Insert the right side of the box. That glyph belongs + to the previous grapheme cluster. */ + MGlyph box_glyph = g[-1]; + + box_glyph.type = GLYPH_BOX; + box_glyph.g.xadv + = (control->fixed_width + ? frame->space_width + : box->inner_hmargin + box->width + box->outer_hmargin); + box_glyph.g.lbearing = 0; + box_glyph.g.rbearing = box_glyph.g.xadv; + box_glyph.g.xoff = 0; + box_glyph.right_padding = 1; + gstring->width += box_glyph.g.xadv; + gstring->rbearing += box_glyph.g.xadv; + INSERT_GLYPH (gstring, gidx, box_glyph); + gidx++; + g = MGLYPH (gidx); + } + box = g->rface->box; + if (box) + { + /* Insert the left side of the box. That glyph belongs + to the following grapheme cluster. */ + MGlyph box_glyph = *g; + int box_height = (box->width + + box->inner_vmargin + box->outer_vmargin); + + if (box_line_height < box_height) + box_line_height = box_height; + box_glyph.type = GLYPH_BOX; + box_glyph.g.xadv + = (control->fixed_width + ? frame->space_width + : box->inner_hmargin + box->width + box->outer_hmargin); + box_glyph.g.lbearing = 0; + box_glyph.g.rbearing = box_glyph.g.xadv; + box_glyph.g.xoff = 0; + box_glyph.left_padding = 1; + gstring->width += box_glyph.g.xadv; + gstring->rbearing += box_glyph.g.xadv; + INSERT_GLYPH (gstring, gidx, box_glyph); + gidx++; + g = MGLYPH (gidx); + } + } + + if (g->category == GLYPH_CATEGORY_FORMATTER && ignore_formatting_char) + g->type = GLYPH_SPACE; + + if (g->type == GLYPH_CHAR) + { + MRealizedFace *rface = g->rface; + MRealizedFont *rfont = rface->rfont; + MGlyph *fromg = g; + int from = GLYPH_INDEX (g); + + for (g++; g->type == GLYPH_CHAR; g++) + if (! rfont != ! g->rface->rfont + || box != g->rface->box + || ((fromg->g.code == MCHAR_INVALID_CODE) + != (g->g.code == MCHAR_INVALID_CODE)) + || (g->category == GLYPH_CATEGORY_FORMATTER + && ignore_formatting_char)) + break; + if (rfont && fromg->g.code != MCHAR_INVALID_CODE) + { + int extra_width; + int to = GLYPH_INDEX (g); + MSubTextExtents extents; + + layout_glyphs (frame, gstring, from, to, &extents); + extra_width = - extents.lbearing; + if (extra_width > 0 + && ! control->disable_overlapping_adjustment + && (! control->orientation_reversed + ? ((to > 1 || control->align_head) + && g->type != GLYPH_ANCHOR) + : (((g->type && GLYPH_ANCHOR) || control->align_head) + && to > 1))) + { + g = MGLYPH (from); + pad = *g; + pad.type = GLYPH_PAD; + pad.g.xoff = 0; + pad.g.lbearing = 0; + pad.g.xadv = pad.g.rbearing = extra_width; + pad.left_padding = 1; + INSERT_GLYPH (gstring, from, pad); + to++; + extents.lbearing = 0; + extents.width += extra_width; + extents.rbearing += extra_width; + + g = MGLYPH (from - 1); + if (g->type == GLYPH_SPACE) + { + /* The pad just inserted is absorbed (maybe + partially) by the previous space while + keeping at least some space width. For the + moment, we use the arbitrary width 2-pixel. + Perhaps, it should be decided by the current + face, or a default value of the current + frame, which is, however, not yet + implemented. */ + if (extra_width + 2 < g->g.xadv) + { + g->g.xadv -= extra_width; + } + else + { + extra_width = g->g.xadv - 2; + g->g.xadv = 2; + } + gstring->width -= extra_width; + gstring->rbearing -= extra_width; + } + } + + g = MGLYPH (to); + extra_width = extents.rbearing - extents.width; + if (extra_width > 0 + && ! control->disable_overlapping_adjustment + && (GLYPH_INDEX (g) < gstring->used - 1 + || (control->orientation_reversed && control->align_head))) + { + if (g->type == GLYPH_SPACE && box == g->rface->box) + { + pad = g[-1]; + pad.type = GLYPH_PAD; + pad.g.xoff = 0; + pad.g.lbearing = 0; + pad.g.xadv = pad.g.rbearing = extra_width; + INSERT_GLYPH (gstring, to, pad); + to++; + g = MGLYPH (to); + } + else + g[-1].g.xadv += extra_width; + extents.width += extra_width; + } + + if (gstring->lbearing > gstring->width + extents.lbearing) + gstring->lbearing = gstring->width + extents.lbearing; + if (gstring->rbearing < gstring->width + extents.rbearing) + gstring->rbearing = gstring->width + extents.rbearing; + gstring->width += extents.width; + if (gstring->ascent < rface->ascent) + gstring->ascent = rface->ascent; + if (gstring->descent < rface->descent) + gstring->descent = rface->descent; + } + else + { + for (; fromg < g; fromg++) + { + if ((fromg->g.c >= 0x200B && fromg->g.c <= 0x200F) + || (fromg->g.c >= 0x202A && fromg->g.c <= 0x202E)) + fromg->g.xadv = fromg->g.rbearing = 1; + else + fromg->g.xadv = fromg->g.rbearing = rface->space_width; + fromg->g.xoff = fromg->g.lbearing = 0; + fromg->g.ascent = fromg->g.descent = 0; + gstring->width += fromg->g.xadv; + gstring->rbearing += fromg->g.xadv; + } + if (gstring->ascent < frame->rface->ascent) + gstring->ascent = frame->rface->ascent; + if (gstring->descent < frame->descent) + gstring->descent = frame->rface->descent; + } + } + else if (g->type == GLYPH_SPACE) + { + if (g->g.c == ' ') + g->g.xadv = g->rface->space_width; + else if (g->g.c == '\n') + { + g->g.xadv = control->cursor_width; + if (g->g.xadv) + { + if (control->cursor_bidi) + g->g.xadv = 3; + else if (g->g.xadv < 0) + g->g.xadv = g->rface->space_width; + } + } + else if (g->g.c == '\t') + { + g->g.xadv = tab_width - ((gstring->indent + gstring->width) + % tab_width); + tab_found = 1; + } + else + g->g.xadv = 1; + if (g[-1].type == GLYPH_PAD) + { + /* This space glyph absorbs (maybe partially) the + previous padding glyph. */ + g->g.xadv -= g[-1].g.xadv; + if (g->g.xadv < 1) + /* But, keep at least some space width. For the + moment, we use the arbitrary width 2-pixel. */ + g->g.xadv = 2; + } + g->g.rbearing = g->g.xadv; + gstring->width += g->g.xadv; + gstring->rbearing += g->g.xadv; + if (g->rface->rfont) + { + if (gstring->ascent < g->rface->ascent) + gstring->ascent = g->rface->ascent; + if (gstring->descent < g->rface->descent) + gstring->descent = g->rface->descent; + } + g++; + } + else + { + gstring->width += g->g.xadv; + gstring->rbearing += g->g.xadv; + g++; + } + } + + if (box) + { + /* Insert the right side of the box. */ + int gidx = GLYPH_INDEX (g); + MGlyph box_glyph = g[-1]; + + box_glyph.type = GLYPH_BOX; + box_glyph.g.xadv + = (control->fixed_width + ? frame->space_width + : box->inner_hmargin + box->width + box->outer_hmargin); + box_glyph.g.lbearing = 0; + box_glyph.g.rbearing = box_glyph.g.xadv; + box_glyph.g.xoff = 0; + box_glyph.right_padding = 1; + gstring->width += box_glyph.g.xadv; + gstring->rbearing += box_glyph.g.xadv; + INSERT_GLYPH (gstring, gidx, box_glyph); + } + + gstring->text_ascent = gstring->ascent; + gstring->text_descent = gstring->descent; + if (gstring->text_ascent < gstring->physical_ascent) + gstring->text_ascent = gstring->physical_ascent; + if (gstring->text_descent < gstring->physical_descent) + gstring->text_descent = gstring->physical_descent; + gstring->line_ascent = gstring->text_ascent; + gstring->line_descent = gstring->text_descent; + if (box_line_height > 0) + { + gstring->line_ascent += box_line_height; + gstring->physical_ascent = gstring->line_ascent; + gstring->line_descent += box_line_height; + gstring->physical_descent = gstring->line_descent; + } + + if (gstring->line_ascent < control->min_line_ascent) + gstring->line_ascent = control->min_line_ascent; + else if (control->max_line_ascent + && control->max_line_ascent > control->min_line_ascent + && gstring->line_ascent > control->max_line_ascent) + gstring->line_ascent = control->max_line_ascent; + + if (gstring->line_descent < control->min_line_descent) + gstring->line_descent = control->min_line_descent; + else if (control->max_line_descent + && control->max_line_descent > control->min_line_descent + && gstring->line_descent > control->max_line_descent) + gstring->line_descent = control->max_line_descent; + gstring->height = gstring->line_ascent + gstring->line_descent; + + if (control->orientation_reversed + && tab_found) + { + /* We must adjust TAB width for RTL orientation. */ + width = gstring->indent; + + for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--) + { + if (g->type == GLYPH_CHAR && g->g.c == '\t') + { + int this_width = tab_width - (width % tab_width); + + if (g[1].type == GLYPH_PAD) + this_width -= g[1].g.xadv; + if (g[-1].type == GLYPH_PAD) + this_width -= g[-1].g.xadv; + if (this_width < 2) + this_width = 2; + gstring->width += this_width - g->g.xadv; + gstring->rbearing += this_width - g->g.xadv; + g->g.xadv = this_width; + width += this_width; + } + else + width += g->g.xadv; + } + } +} + + +static MDrawRegion +draw_background (MFrame *frame, MDrawWindow win, int x, int y, + MGlyphString *gstring, int from, int to, + int *from_idx, int *to_idx, int *to_x) +{ + MGlyph *g = MGLYPH (1); + MDrawRegion region = (MDrawRegion) NULL; + MDrawControl *control = &gstring->control; + int cursor_pos = -1; + int prev_pos = -1; + int cursor_bidi = control->cursor_bidi; + + if (control->with_cursor && control->cursor_width) + { + if (gstring->from <= control->cursor_pos + && gstring->to > control->cursor_pos) + cursor_pos = control->cursor_pos; + if (cursor_pos >= 0 + && cursor_bidi + && gstring->from <= control->cursor_pos - 1 + && gstring->to > control->cursor_pos - 1) + prev_pos = control->cursor_pos - 1; + } + + *from_idx = *to_idx = 0; + *to_x = x; + while (g->type != GLYPH_ANCHOR) + { + if (g->g.from >= from && g->g.from < to) + { + MGlyph *fromg = g, *cursor = NULL; + MRealizedFace *rface = g->rface; + int width = 0; + int cursor_width = 0; + int cursor_x; + + if (! *from_idx) + *from_idx = GLYPH_INDEX (g); + while (g->g.from >= from && g->g.from < to + && g->rface == rface) + { + g->enabled = 1; + if (g->type != GLYPH_BOX + && g->g.from <= cursor_pos && g->g.to > cursor_pos) + { + if (! cursor) + cursor = g, cursor_x = x + width; + cursor_width += g->g.xadv; + } + width += g++->g.xadv; + } + if (width > 0 + && (control->as_image + || rface->face.property[MFACE_VIDEOMODE] == Mreverse)) + { + int this_x = x, this_width = width; + + if (fromg->type == GLYPH_BOX) + this_x += fromg->g.xadv, this_width -= fromg->g.xadv; + if (g[-1].type == GLYPH_BOX) + this_width -= g[-1].g.xadv; + (frame->driver->fill_space) + (frame, win, rface, 0, + this_x, y - gstring->text_ascent, this_width, + gstring->text_ascent + gstring->text_descent, + control->clip_region); + } + if (cursor) + { + MDrawMetric rect; + + rect.x = cursor_x; + rect.y = y - gstring->text_ascent; + rect.height = gstring->text_ascent + gstring->text_descent; + if (! cursor_bidi) + { + rect.width = ((control->cursor_width > 0 + && control->cursor_width < cursor_width) + ? control->cursor_width : cursor_width); + } + else + rect.width = 1; + if (cursor->bidi_level % 2) + rect.x += cursor_width - rect.width; + (*frame->driver->fill_space) + (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height, + control->clip_region); + if (! region) + region = (*frame->driver->region_from_rect) (&rect); + else + (*frame->driver->region_add_rect) (region, &rect); + if (cursor_bidi) + { + if (cursor->bidi_level % 2) + rect.x -= 3; + rect.height = 2; + rect.width = cursor_width < 4 ? cursor_width : 4; + (*frame->driver->fill_space) + (frame, win, rface, 1, + rect.x, rect.y, rect.width, rect.height, + control->clip_region); + (*frame->driver->region_add_rect) (region, &rect); + } + } + + if (prev_pos >= 0) + { + int temp_width = 0; + + cursor_width = 0; + cursor = NULL; + while (fromg < g) + { + if (fromg->type != GLYPH_BOX + && fromg->g.from <= prev_pos && fromg->g.to > prev_pos) + { + if (! cursor) + cursor = fromg, cursor_x = x + temp_width; + cursor_width += fromg->g.xadv; + } + temp_width += fromg++->g.xadv; + } + if (cursor) + { + MDrawMetric rect; + + rect.x = cursor_x; + if (! (cursor->bidi_level % 2)) + rect.x += cursor_width - 1; + rect.y = y - gstring->text_ascent; + rect.height = gstring->text_ascent + gstring->text_descent; + rect.width = 1; + (*frame->driver->fill_space) + (frame, win, rface, 1, + rect.x, rect.y, rect.width, rect.height, + control->clip_region); + if (! region) + region = (*frame->driver->region_from_rect) (&rect); + else + (*frame->driver->region_add_rect) (region, &rect); + rect.y += rect.height - 2; + rect.height = 2; + rect.width = cursor_width < 4 ? cursor_width : 4; + if (! (cursor->bidi_level % 2)) + rect.x -= rect.width - 1; + (*frame->driver->fill_space) (frame, win, rface, 1, + rect.x, rect.y, rect.width, rect.height, + control->clip_region); + (*frame->driver->region_add_rect) (region, &rect); + } + } + x += width; + *to_idx = GLYPH_INDEX (g); + *to_x = x; + } + else + g++->enabled = 0; + } + return region; +} + +static void +render_glyphs (MFrame *frame, MDrawWindow win, int x, int y, int width, + MGlyphString *gstring, int from_idx, int to_idx, + int reverse, MDrawRegion region) +{ + MGlyph *g = MGLYPH (from_idx), *gend = MGLYPH (to_idx); + + if (region) + { + MDrawMetric rect; + + (*frame->driver->region_to_rect) (region, &rect); + if (rect.x > x) + { + while (g != gend && x + g->g.rbearing <= rect.x) + { + x += g->g.xadv; + width -= g++->g.xadv; + while (! g->enabled && g != gend) + g++; + } + } + rect.x += rect.width; + if (rect.x < x + width) + { + while (g != gend + && (x + width - gend[-1].g.xadv + gend[-1].g.lbearing >= rect.x)) + { + width -= (--gend)->g.xadv; + while (! gend->enabled && g != gend) + gend--; + } + if (g != gend) + while (gend->type != GLYPH_ANCHOR && gend[-1].g.to == gend->g.to) + gend++; + } + } + + while (g != gend) + { + if (g->enabled) + { + MRealizedFace *rface = g->rface; + int width = g->g.xadv; + MGlyph *from_g = g++; + + /* Handle the glyphs of the same type/face at once. */ + while (g != gend + && g->type == from_g->type + && g->rface == rface + && ((g->g.code == MCHAR_INVALID_CODE) + == (from_g->g.code == MCHAR_INVALID_CODE)) + && g->enabled) + width += g++->g.xadv; + + if (from_g->type == GLYPH_CHAR) + { + if (rface->rfont && from_g->g.code != MCHAR_INVALID_CODE) + (rface->rfont->driver->render) (win, x, y, gstring, from_g, g, + reverse, region); + else + (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g, + reverse, region); + } + else if (from_g->type == GLYPH_BOX) + { + /* Draw the left or right side of a box. If + from_g->lbearing is nonzero, this is the left side, + else this is the right side. */ + (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region); + } + + if (from_g->type != GLYPH_BOX) + { + if (rface->hline) + (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse, + x, y, width, region); + if (rface->box + && ! reverse) + /* Draw the top and bottom side of a box. */ + (*frame->driver->draw_box) (frame, win, gstring, from_g, + x, y, width, region); + } + x += width; + } + else + g++; + } +} + + +static int +find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right, + int *from_x, int *to_x) +{ + MGlyph *g; + int left_idx = *left, right_idx = *right; + int left_x, right_x, x; + + for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--) + { + x -= g->g.xadv; + if (x + g->g.rbearing > 0) + { + while (g[-1].g.from == g->g.from && g[-1].type != GLYPH_ANCHOR) + x -= (--g)->g.xadv; + left_idx = GLYPH_INDEX (g); + left_x = x; + } + } + + for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++) + { + x += g->g.xadv; + if (x - g->g.xadv + g->g.lbearing < 0) + { + while (g->g.from == g[1].g.from && g[1].type != GLYPH_ANCHOR) + x += (++g)->g.xadv; + right_idx = GLYPH_INDEX (g) + 1; + right_x = x; + } + } + + if (*left == left_idx && *right == right_idx) + return 0; + + if (*left != left_idx) + { + for (g = MGLYPH (*left) - 1; GLYPH_INDEX (g) >= left_idx; g--) + g->enabled = 1; + *left = left_idx; + *from_x += left_x; + } + if (*right != right_idx) + { + for (g = MGLYPH (*right); GLYPH_INDEX (g) < right_idx; g++) + g->enabled = 1; + *right = right_idx; + *to_x += right_x; + } + return 1; +} + + +static int +gstring_width (MGlyphString *gstring, int from, int to, + int *lbearing, int *rbearing) +{ + MGlyph *g; + int width; + + if (from <= gstring->from && to >= gstring->to) + { + if (lbearing) + *lbearing = gstring->lbearing; + if (rbearing) + *rbearing = gstring->rbearing; + return gstring->width; + } + + if (lbearing) + *lbearing = 0; + if (rbearing) + *rbearing = 0; + for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++) + if (g->g.from >= from && g->g.from < to) + { + if (lbearing && width + g->g.lbearing < *lbearing) + *lbearing = width + g->g.lbearing; + if (rbearing && width + g->g.rbearing > *rbearing) + *rbearing = width + g->g.rbearing; + width += g->g.xadv; + } + return width; +} + + +static void +render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y, + MGlyphString *gstring, int from, int to) +{ + MDrawControl *control = &gstring->control; + MDrawMetric rect; + MDrawRegion clip_region, cursor_region; + int from_idx, to_idx; + int to_x; + + if (from == to) + return; + if (control->orientation_reversed) + x -= gstring->indent + gstring_width (gstring, from, to, NULL, NULL); + else + x += gstring->indent; + + /* At first, draw all glyphs without cursor. */ + cursor_region = draw_background (frame, win, x, y, gstring, from, to, + &from_idx, &to_idx, &to_x); + + if (control->partial_update) + { + rect.x = x; + rect.width = to_x - x; + if (find_overlapping_glyphs (gstring, &from_idx, &to_idx, &x, &to_x)) + { + rect.y = y - gstring->line_ascent; + rect.height = gstring->height; + clip_region = (*frame->driver->region_from_rect) (&rect); + if (control->clip_region) + (*frame->driver->intersect_region) (clip_region, control->clip_region); + } + else + clip_region = control->clip_region; + } + else + clip_region = control->clip_region; + + render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx, + 0, clip_region); + if (cursor_region) + { + if (clip_region) + (*frame->driver->intersect_region) (cursor_region, clip_region); + render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx, + 1, cursor_region); + } + if (clip_region != control->clip_region) + (*frame->driver->free_region) (clip_region); + if (cursor_region) + (*frame->driver->free_region) (cursor_region); + return; +} + +static int gstring_num; + +static void +free_gstring (void *object) +{ + MGlyphString *gstring = (MGlyphString *) object; + + if (gstring->next) + free_gstring (gstring->next); + if (gstring->size > 0) + free (gstring->glyphs); + free (gstring); + gstring_num--; +} + + +static MGlyphString scratch_gstring; + +static MGlyphString * +alloc_gstring (MFrame *frame, MText *mt, int pos, MDrawControl *control, + int line, int y) +{ + MGlyphString *gstring; + + if (pos == mt->nchars) + { + MGlyph *g; + + gstring = &scratch_gstring; + if (gstring->size == 0) + { + MGlyph g_tmp; + + INIT_GLYPH (g_tmp); + g_tmp.type = GLYPH_ANCHOR; + APPEND_GLYPH (gstring, g_tmp); + APPEND_GLYPH (gstring, g_tmp); + APPEND_GLYPH (gstring, g_tmp); + gstring->glyphs[1].type = GLYPH_SPACE; + gstring->glyphs[1].g.c = '\n'; + gstring->glyphs[1].g.code = '\n'; + } + gstring->from = pos; + g = MGLYPH (0); + g->rface = frame->rface; + g->g.from = g->g.to = pos; + g++; + g->rface = frame->rface; + g->g.from = pos++, g->g.to = pos; + g++; + g->rface = frame->rface; + g->g.from = g->g.to = pos; + gstring->to = pos; + } + else + { + M17N_OBJECT (gstring, free_gstring, MERROR_DRAW); + MLIST_INIT1 (gstring, glyphs, 128); + gstring_num++; + } + + gstring->frame = frame; + gstring->tick = frame->tick; + gstring->top = gstring; + gstring->control = *control; + gstring->indent = gstring->width_limit = 0; + if (control->format) + (*control->format) (line, y, &(gstring->indent), &(gstring->width_limit)); + else + gstring->width_limit = control->max_line_width; + gstring->anti_alias = control->anti_alias; + return gstring; +} + +static MGlyph *find_glyph_in_gstring (MGlyphString *gstring, int pos, + int forwardp); + +/* Truncate the line width of GSTRING to GSTRING->width_limit. */ + +static void +truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring) +{ + int width; + int i; + int *pos_width; + MGlyph *g; + int pos; + + /* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is + a width of glyphs for the character at I of MT. If I is not a + beginning of a grapheme cluster, the corresponding element is + 0. */ + MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW); + memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from)); + for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++) + pos_width[g->g.from - gstring->from] += g->g.xadv; + for (i = 0, width = 0; i < gstring->to - gstring->from; i++) + { + if (pos_width[i] > 0) + { + if (width + pos_width[i] > gstring->width_limit) + break; + } + width += pos_width[i]; + } + + pos = gstring->from + i; + if (gstring->control.line_break) + { + pos = (*gstring->control.line_break) (mt, gstring->from + i, + gstring->from, gstring->from + i, + 0, 0); + if (pos <= gstring->from) + { + g = find_glyph_in_gstring (gstring, gstring->from, 1); + pos = g->g.to; + } + else if (pos >= gstring->to) + pos = gstring->to; + } + else if (i == 0) + { + g = find_glyph_in_gstring (gstring, gstring->from, 1); + pos = g->g.to; + } + if (pos < gstring->to) + { + compose_glyph_string (frame, mt, gstring->from, pos, gstring); + layout_glyph_string (frame, gstring); + } +} + + +/* Return a gstring that covers a character at POS. */ + +static MGlyphString * +get_gstring (MFrame *frame, MText *mt, int pos, int to, MDrawControl *control) +{ + MGlyphString *gstring = NULL; + + if (pos < mtext_nchars (mt)) + { + MTextProperty *prop = mtext_get_property (mt, pos, M_glyph_string); + + if (prop + && ((prop->start != 0 + && mtext_ref_char (mt, prop->start - 1) != '\n') + || (prop->end < mtext_nchars (mt) + && mtext_ref_char (mt, prop->end - 1) != '\n'))) + { + mtext_detach_property (prop); + prop = NULL; + } + if (prop) + { + gstring = prop->val; + if (gstring->frame != frame + || gstring->tick != frame->tick + || memcmp (control, &gstring->control, + (char *) (&control->with_cursor) + - (char *) (control)) + || control->cursor_pos != gstring->control.cursor_pos + || control->cursor_width != gstring->control.cursor_width + || control->cursor_bidi != gstring->control.cursor_bidi) + { + mtext_detach_property (prop); + gstring = NULL; + } + } + } + else if (! control->cursor_width) + return NULL; + + if (gstring) + { + MGlyphString *gst; + int offset; + + offset = mtext_character (mt, pos, 0, '\n'); + if (offset < 0) + offset = 0; + else + offset++; + offset -= gstring->from; + if (offset) + for (gst = gstring; gst; gst = gst->next) + { + int i; + + gst->from += offset; + gst->to += offset; + for (i = 0; i < gst->used; i++) + { + gst->glyphs[i].g.from += offset; + gst->glyphs[i].g.to += offset; + } + } + M17N_OBJECT_REF (gstring); + } + else + { + int beg, end; + int line = 0, y = 0; + + if (pos < mtext_nchars (mt)) + { + beg = mtext_character (mt, pos, 0, '\n'); + if (beg < 0) + beg = 0; + else + beg++; + } + else + beg = pos; + end = mtext_nchars (mt) + (control->cursor_width != 0); + gstring = alloc_gstring (frame, mt, beg, control, line, y); + if (beg < mtext_nchars (mt)) + compose_glyph_string (frame, mt, beg, end, gstring); + layout_glyph_string (frame, gstring); + end = gstring->to; + if (gstring->width_limit + && gstring->width > gstring->width_limit) + { + MGlyphString *gst = gstring; + + truncate_gstring (frame, mt, gst); + while (gst->to < end) + { + line++, y += gst->height; + gst->next = alloc_gstring (frame, mt, gst->from, control, + line, y); + gst->next->top = gstring; + compose_glyph_string (frame, mt, gst->to, end, gst->next); + gst = gst->next; + layout_glyph_string (frame, gst); + if (gst->width <= gst->width_limit) + break; + truncate_gstring (frame, mt, gst); + } + } + + if (! control->disable_caching && pos < mtext_nchars (mt)) + { + MTextProperty *prop = mtext_property (M_glyph_string, gstring, + MTEXTPROP_VOLATILE_STRONG); + + if (end > mtext_nchars (mt)) + end = mtext_nchars (mt); + mtext_attach_property (mt, beg, end, prop); + M17N_OBJECT_UNREF (prop); + } + } + + while (gstring->to <= pos) + { + if (! gstring->next) + mdebug_hook (); + gstring = gstring->next; + } + gstring->control = *control; + + return gstring; +} + + +static MDrawControl control_noop; + +#define ASSURE_CONTROL(control) \ + if (! control) \ + control = &control_noop; \ + else + + +static int +draw_text (MFrame *frame, MDrawWindow win, int x, int y, + MText *mt, int from, int to, + MDrawControl *control) +{ + MGlyphString *gstring; + + M_CHECK_POS_X (mt, from, -1); + ASSURE_CONTROL (control); + if (to > mtext_nchars (mt) + (control->cursor_width != 0)) + to = mtext_nchars (mt) + (control->cursor_width != 0); + else if (to < from) + to = from; + + gstring = get_gstring (frame, mt, from, to, control); + if (! gstring) + MERROR (MERROR_DRAW, -1); + render_glyph_string (frame, win, x, y, gstring, from, to); + from = gstring->to; + while (from < to) + { + y += gstring->line_descent; + M17N_OBJECT_UNREF (gstring->top); + gstring = get_gstring (frame, mt, from, to, control); + y += gstring->line_ascent; + render_glyph_string (frame, win, x, y, gstring, from, to); + from = gstring->to; + } + M17N_OBJECT_UNREF (gstring->top); + + return 0; +} + + +static MGlyph * +find_glyph_in_gstring (MGlyphString *gstring, int pos, int forwardp) +{ + MGlyph *g; + + if (forwardp) + { + for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++) + if (g->g.from <= pos && g->g.to > pos) + break; + } + else + { + for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--) + if (g->g.from <= pos && g->g.to > pos) + break; + } + return g; +} + + +/* for debugging... */ +char work[16]; + +void +dump_gstring (MGlyphString *gstring, int indent, int type) +{ + char *prefix = (char *) alloca (indent + 1); + MGlyph *g, *first_g, *last_g; + + memset (prefix, 32, indent); + prefix[indent] = 0; + + fprintf (stderr, "(glyph-string"); + + if (type == 0) + { + first_g = MGLYPH (0); + last_g = first_g + gstring->used; + } + else + { + first_g = (MGlyph *) ((MFLTGlyphString *) gstring)->glyphs; + last_g = first_g + ((MFLTGlyphString *) gstring)->used; + } + + for (g = first_g; g < last_g; g++) + { + fprintf (stderr, + "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x w:%02d bidi:%d", + prefix, + g - first_g, + (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD" + : g->type == GLYPH_ANCHOR ? "ANC" + : g->type == GLYPH_BOX ? "BOX" : "CHR"), + g->g.from, g->g.to, g->g.c, g->g.code, (unsigned) g->rface, + g->g.xadv, g->bidi_level); + if (g->g.xoff || g->g.yoff) + fprintf (stderr, " off:%d,%d", g->g.xoff, g->g.yoff); + fprintf (stderr, ")"); + } + fprintf (stderr, ")"); +} + + +/* m17n-X internal APIs */ + +int +mdraw__init () +{ + M_glyph_string = msymbol_as_managing_key (" glyph-string"); + + memset (&scratch_gstring, 0, sizeof (scratch_gstring)); + MLIST_INIT1 (&scratch_gstring, glyphs, 3); + + Mcommon = msymbol ("common"); + + McatCc = msymbol ("Cc"); + McatCf = msymbol ("Cf"); + + MbidiR = msymbol ("R"); + MbidiAL = msymbol ("AL"); + MbidiRLE = msymbol ("RLE"); + MbidiRLO = msymbol ("RLO"); + MbidiBN = msymbol ("BN"); + MbidiS = msymbol ("S"); + MbidiNSM = msymbol ("NSM"); +#ifdef HAVE_FRIBIDI +#if FRIBIDI_INTERFACE_VERSION < 3 + fribidi_set_mirroring (TRUE); +#else + fribidi_set_mirroring (1); +#endif +#endif + + M_break_at_space = msymbol ("bs"); + M_break_at_word = msymbol ("bw"); + M_break_at_any = msymbol ("ba"); + M_kinsoku_bol = msymbol ("kb"); + M_kinsoku_eol = msymbol ("ke"); + + mflt_enable_new_feature = 1; + + return 0; +} + +void +mdraw__fini () +{ + MLIST_FREE1 (&scratch_gstring, glyphs); + M17N_OBJECT_UNREF (linebreak_table); + linebreak_table = NULL; +} + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/* External API */ +/*** @addtogroup m17nDraw */ +/*** @{ */ + +/*=*/ +/***en + @brief Draw an M-text on a window. + + The mdraw_text () function draws the text between $FROM and $TO of + M-text $MT on window $WIN of frame $FRAME at coordinate ($X, $Y). + + The appearance of the text (size, style, color, etc) is specified + by the value of the text property whose key is @c Mface. If the + M-text or a part of the M-text does not have such a text property, + the default face of $FRAME is used. + + The font used to draw a character in the M-text is selected from + the value of the fontset property of a face by the following + algorithm: + +
    + +
  1. Search the text properties given to the character for the one + whose key is @c Mcharset; its value should be either a symbol + specifying a charset or #Mnil. If the value is #Mnil, + proceed to the next step. + + Otherwise, search the mapping table of the fontset for the + charset. If no entry is found proceed to the next step. + + If an entry is found, use one of the fonts in the entry that + has a glyph for the character and that matches best with the + face properties. If no such font exists, proceed to the next + step. + +
  2. Get the character property "script" of the character. If it is + inherited, get the script property from the previous + characters. If there is no previous character, or none of + them has the script property other than inherited, proceed to + the next step. + + Search the text properties given to the character for the one + whose key is @c Mlanguage; its value should be either a + symbol specifying a language or @c Mnil. + + Search the mapping table of the fontset for the combination + of the script and language. If no entry is found, proceed to + the next step. + + If an entry is found, use one of the fonts in the entry that + has a glyph for the character and that matches best with the + face properties. If no such font exists, proceed to the next + step. + +
  3. Search the fall-back table of the fontset for a font that has + a glyph of the character. If such a font is found, use that + font. + +
+ + If no font is found by the algorithm above, this function draws an + empty box for the character. + + This function draws only the glyph foreground. To specify the + background color, use mdraw_image_text () or + mdraw_text_with_control (). + + This function is the counterpart of XDrawString (), + XmbDrawString (), and XwcDrawString () functions + in the X Window System. + + @return + If the operation was successful, mdraw_text () returns 0. If an + error is detected, it returns -1 and assigns an error code to the + external variable #merror_code. */ +/***ja + @brief ������ɥ��� M-text �����褹��. + + �ؿ� mdraw_text () �ϡ��ե졼�� $FRAME �Υ�����ɥ� $WIN �κ�ɸ + ($X, $Y) �ˡ�M-text $MT �� $FROM ���� $TO �ޤǤΥƥ����Ȥ����褹�롣 + + �ƥ����Ȥθ��ɤ��ʥե���ȡ��������롢���ʤɡˤϡ������� @c Mface + �Ǥ���ƥ����ȥץ��ѥƥ����ͤˤ�äƷ�ޤ롣M-text + �ΰ������뤤�������ˤ��Τ褦�ʥƥ����ȥץ��ѥƥ����դ��Ƥ��ʤ����ˤϡ�$FRAME + �Υǥե���ȥե�������������Ѥ��롣 + + M-text �γ�ʸ����ɽ������ե���Ȥϡ��ե������� fontset + �ץ��ѥƥ����ͤΤ������顢�ʲ��Υ��르�ꥺ������Ф�롣 + +
    + +
  1. ����ʸ���Υƥ����ȥץ��ѥƥ��Τ����������� @c Mcharset + �Ǥ����Τ��ͤ�Ĵ�٤롣�����ͤ�ʸ�����åȤ�ɽ�魯����ܥ뤫 #Mnil + �Τɤ��餫�Ǥ��롣#Mnil �ʤ�С����Υ��ƥåפ˿ʤࡣ + �����Ǥʤ���С�fontset + �Υޥåԥ󥰥ơ��֥�ˤ���ʸ�����å��ѤΥե���Ȥ����뤫�ɤ�����Ĵ�٤롣 + ̵����С����Υ��ƥåפ˿ʤࡣ + + ����ʸ�����å��ѤΥե���Ȥ��ߤĤ���С������Τ������ߤ�ʸ���ѤΥ���դ�������ե������γƥץ��ѥƥ��˺Ǥ�褯���פ����Τ�Ȥ��� + ���Τ褦�ʥե���Ȥ�̵����м��Υ��ƥåפ˿ʤࡣ + +
  2. ����ʸ����ʸ���ץ��ѥƥ� "script" �ʥ�����ץȡˤ�Ĵ�٤롣 + ���Υץ��ѥƥ����Ѿ�����Ƥ���ʤ�Ф��������ʸ����ʸ���ץ��ѥƥ� "script" + ��Ĵ�٤롣����ʸ�����ʤ��ä��ꡢ����ʸ���ץ��ѥƥ�����äƤ��ʤ��ä����ˤϡ����Υ��ƥåפ˿ʤࡣ + + ����ʸ���Υƥ����ȥץ��ѥƥ��Τ����������� @c Mlanguage �Ǥ����Τ��ͤ�Ĵ�٤롣 + �����ͤϸ����ɽ�魯����ܥ뤫 @c Mnil �Τ����줫�Ǥ��롣 + + ���θ���ȥ�����ץȤ��Ȥ߹�碌�� fontset + �Υޥåԥ󥰥ơ��֥�ˤ��뤫�ɤ�����Ĵ�٤롣���Ĥ���ʤ���м��Υ��ƥåפ˿ʤࡣ + + ���Ĥ��ä��Ф����ˤϡ������Υե���ȤΤ������ߤ�ʸ���ѤΥ���դ�������ե������γƥץ��ѥƥ��˺Ǥ�褯���פ��Ƥ����Τ�Ȥ��� + ���Τ褦�ʥե���Ȥ�̵����м��Υ��ƥåפ˿ʤࡣ + +
  3. ����ʸ���Υ���դ���ĥե���Ȥ򡢥ե���ȥ��åȤ� fall-back + �ơ��֥뤫��õ�����ե���Ȥ����Ĥ���Ф����Ȥ��� + +
+ + �ʾ�Υ��르�ꥺ��ǥե���Ȥ����Ĥ���ʤ���С����δؿ��Ϥ���ʸ���Ȥ��ƶ��λͳѷ���ɽ�����롣 + + ���δؿ������褹��Τϥ���դ����ʤ����Ǥ��롣�طʿ�����ꤹ��ˤϡ��ؿ� + mdraw_image_text () ���ؿ� mdraw_text_with_control () ��Ȥ����ȡ� + + ���δؿ��ϡ�X ������ɥ��ˤ�����ؿ� XDrawString (), + XmbDrawString (), XwcDrawString () ���������롣 + + @return + ����������������硢mdraw_text () �� 0 �֤������顼�����Ф��줿���� + -1 ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mdraw_text} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE + + @seealso + mdraw_image_text () */ + +int +mdraw_text (MFrame *frame, MDrawWindow win, int x, int y, + MText *mt, int from, int to) +{ + MDrawControl control; + + M_CHECK_WRITABLE (frame, MERROR_DRAW, -1); + memset (&control, 0, sizeof control); + control.as_image = 0; + return draw_text (frame, win, x, y, mt, from, to, &control); +} + +/*=*/ + + +/***en + @brief Draw an M-text on a window as an image. + + The mdraw_image_text () function draws the text between $FROM and + $TO of M-text $MT as image on window $WIN of frame $FRAME at + coordinate ($X, $Y). + + The way to draw a text is the same as in mdraw_text () except that + this function also draws the background with the color specified + by faces. + + This function is the counterpart of XDrawImageString (), + XmbDrawImageString (), and XwcDrawImageString () + functions in the X Window System. + + @return + If the operation was successful, mdraw_image_text () returns 0. + If an error is detected, it returns -1 and assigns an error code + to the external variable #merror_code. */ + +/***ja + @brief �ǥ����ץ쥤��M-text ������Ȥ�������. + + �ؿ� mdraw_image_text () �ϡ��ե졼�� $FRAME �Υ�����ɥ� $WIN + �κ�ɸ ($X, $Y) �ˡ�M-text $MT �� $FROM ���� $TO + �ޤǤΥƥ����Ȥ�����Ȥ��������� + + �ƥ����Ȥ�������ˡ�� mdraw_text () + �Ȥۤ�Ʊ���Ǥ��뤬�����δؿ��Ǥϥե������ǻ��ꤵ�줿�����طʤ����������ۤʤäƤ��롣 + + ���δؿ��ϡ�X ������ɥ��ˤ����� XDrawImageString (), + XmbDrawImageString (), XwcDrawImageString () + ���������롣 + + @return + ����������������硢mdraw_image_text () �� 0 + ���֤������顼�����Ф��줿���� -1 ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mdraw_image_text} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE + + @seealso + mdraw_text () */ + +int +mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y, + MText *mt, int from, int to) +{ + MDrawControl control; + + M_CHECK_WRITABLE (frame, MERROR_DRAW, -1); + memset (&control, 0, sizeof control); + control.as_image = 1; + return draw_text (frame, win, x, y, mt, from, to, &control); +} + +/*=*/ + +/***en + @brief Draw an M-text on a window with fine control. + + The mdraw_text_with_control () function draws the text between + $FROM and $TO of M-text $MT on windows $WIN of frame $FRAME at + coordinate ($X, $Y). + + The way to draw a text is the same as in mdraw_text () except that + this function also follows what specified in the drawing control + object $CONTROL. + + For instance, if \ of $CONTROL is nonzero, this + function draw an M-text 2-dimensionally, i.e., newlines in M-text + breaks lines and the following characters are drawn in the next + line. See the documentation of the structure @ MDrawControl for + more detail. */ + +/***ja + @brief �ǥ����ץ쥤��M-text ��ܺ٤�����Ĥ�������. + + �ؿ� mdraw_text_with_control () �ϡ��ե졼�� $FRAME �Υ�����ɥ� + $WIN �κ�ɸ ($X, $Y) �ˡ�M-text $MT �� $FROM ���� $TO �ޤǤΥƥ��� + �Ȥ������� + + �ƥ����Ȥ�������ˡ�� mdraw_text () �Ȥۤ�Ʊ���Ǥ��뤬�����δؿ������������ѤΥ��֥������� + $CONTROL �λؼ��ˤ⽾�������ۤʤäƤ��롣 + + ���Ȥ��� $CONTROL �� \ �������Ǥʤ���С����δؿ��� + M-text ��2����Ū�����������ʤ�� M-text ��β��ԤǹԤ���ᡢ³��ʸ���ϼ��ιԤ��������ܺ٤Ϲ�¤�� + @ MDrawControl �������򻲾Ȥ��뤳�ȡ�*/ + +int +mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y, + MText *mt, int from, int to, MDrawControl *control) +{ + M_CHECK_WRITABLE (frame, MERROR_DRAW, -1); + return draw_text (frame, win, x, y, mt, from, to, control); +} + +/*=*/ + +/***en + @brief Compute text pixel width. + + The mdraw_text_extents () function computes the width of text + between $FROM and $TO of M-text $MT when it is drawn on a window + of frame $FRAME using the mdraw_text_with_control () function with + the drawing control object $CONTROL. + + If $OVERALL_INK_RETURN is not @c NULL, this function also computes + the bounding box of character ink of the M-text, and stores the + results in the members of the structure pointed to by + $OVERALL_INK_RETURN. If the M-text has a face specifying a + surrounding box, the box is included in the bounding box. + + If $OVERALL_LOGICAL_RETURN is not @c NULL, this function also + computes the bounding box that provides minimum spacing to other + graphical features (such as surrounding box) for the M-text, and + stores the results in the members of the structure pointed to by + $OVERALL_LOGICAL_RETURN. + + If $OVERALL_LINE_RETURN is not @c NULL, this function also + computes the bounding box that provides minimum spacing to the + other M-text drawn, and stores the results in the members of the + structure pointed to by $OVERALL_LINE_RETURN. This is a union of + $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN if the members + min_line_ascent, min_line_descent, max_line_ascent, and + max_line_descent of $CONTROL are all zero. + + @return + This function returns the width of the text to be drawn in the + unit of pixels. If $CONTROL->two_dimensional is nonzero and the + text is drawn in multiple physical lines, it returns the width of + the widest line. If an error occurs, it returns -1 and assigns an + error code to the external variable #merror_code. */ + + +/***ja + @brief �ƥ����Ȥ����ʥԥ�����ñ�̡ˤ�׻�����. + + �ؿ� mdraw_text_extents () �ϡ��ؿ� mdraw_text_with_control () + ���������楪�֥������� $CONTROL ���Ѥ��� M-text $MT �� $FROM ���� $TO + �ޤǤ�ե졼�� $FRAME ��ɽ������ݤ�ɬ�פȤʤ������֤��� + + $OVERALL_INK_RETURN �� @c NULL �Ǥʤ���С����δؿ��� M-text + ��ʸ���Υ��󥯤ΥХ���ǥ��󥰥ܥå�����׻�����$OVERALL_INK_RETURN + ���ؤ���¤�ΤΥ��Фˤ��η�̤����ꤹ�롣M-text �˰Ϥ��� (surrounding box) + ����ꤹ��ե�����������С������Х���ǥ��󥰥ܥå����˴ޤࡣ + + $OVERALL_LOGICAL_RETURN �� @c NULL �Ǥʤ���С����δؿ��� M-text + ��¾�� graphical feature �ʰϤ��Ȥʤɡ� + �Ȥδ֤κǾ��Υ��ڡ����򼨤��Х���ǥ��󥰥ܥå�����׻�����$OVERALL_LOGICAL_RETURN + ���ؤ���¤�ΤΥ��Фˤ��η�̤����ꤹ�롣 + + $OVERALL_LINE_RETURN �� @c NULL �Ǥʤ���С����δؿ���¾�� M-text + �Ȥδ֤κǾ��Υ��ڡ����򼨤��Х���ǥ��󥰥ܥå�����׻����� + $OVERALL_LINE_RETURN ���ؤ���¤�ΤΥ��Фˤ��η�̤����ꤹ�롣���֥������� + $CONTROL �Υ��� min_line_ascent, min_line_descent, + max_line_ascent, max_line_descent �����٤�0�λ��ˤϡ������ͤ� + $OVERALL_INK_RETURN ��$OVERALL_LOGICAL_RETURN ���¤Ȥʤ롣 + + @return + ���δؿ���ɽ����ɬ�פʥƥ����Ȥ�����ԥ�����ñ�̤��֤���$CONTROL->two_dimensional + ��0�Ǥʤ����ƥ����Ȥ�ʣ���ιԤ��Ϥä����������ˤϡ�����������֤������顼������������ + -1 ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mdraw_text_extents} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE */ + +int +mdraw_text_extents (MFrame *frame, + MText *mt, int from, int to, MDrawControl *control, + MDrawMetric *overall_ink_return, + MDrawMetric *overall_logical_return, + MDrawMetric *overall_line_return) +{ + MGlyphString *gstring; + int y = 0; + int width, lbearing, rbearing; + + ASSURE_CONTROL (control); + M_CHECK_POS_X (mt, from, -1); + if (to > mtext_nchars (mt) + (control->cursor_width != 0)) + to = mtext_nchars (mt) + (control->cursor_width != 0); + else if (to < from) + to = from; + + gstring = get_gstring (frame, mt, from, to, control); + if (! gstring) + MERROR (MERROR_DRAW, -1); + width = gstring_width (gstring, from, to, &lbearing, &rbearing); + if (overall_ink_return) + overall_ink_return->y = - gstring->physical_ascent; + if (overall_logical_return) + overall_logical_return->y = - gstring->ascent; + if (overall_line_return) + overall_line_return->y = - gstring->line_ascent; + + for (from = gstring->to; from < to; from = gstring->to) + { + int this_width, this_lbearing, this_rbearing; + + y += gstring->line_descent; + M17N_OBJECT_UNREF (gstring->top); + gstring = get_gstring (frame, mt, from, to, control); + this_width = gstring_width (gstring, from, to, + &this_lbearing, &this_rbearing); + y += gstring->line_ascent; + if (width < this_width) + width = this_width; + if (rbearing < this_rbearing) + rbearing = this_rbearing; + if (lbearing > this_lbearing) + lbearing = this_lbearing; + } + if (overall_ink_return) + { + overall_ink_return->x = lbearing; + overall_ink_return->width = rbearing - lbearing; + overall_ink_return->height + = y + gstring->physical_descent - overall_ink_return->y; + } + if (overall_logical_return) + { + overall_logical_return->x = 0; + overall_logical_return->width = width; + overall_logical_return->height + = y + gstring->descent - overall_logical_return->y; + } + if (overall_line_return) + { + overall_line_return->x = lbearing; + overall_line_return->width = MAX (width, rbearing - lbearing); + overall_line_return->height + = y + gstring->line_descent - overall_line_return->y; + } + + M17N_OBJECT_UNREF (gstring->top); + return width; +} + +/*=*/ + +/***en + @brief Compute the text dimensions of each character of M-text. + + The mdraw_text_per_char_extents () function computes the drawn + metric of each character between $FROM and $TO of M-text $MT + assuming that they are drawn on a window of frame $FRAME using the + mdraw_text_with_control () function with the drawing control + object $CONTROL. + + $ARRAY_SIZE specifies the size of $INK_ARRAY_RETURN and + $LOGICAL_ARRAY_RETURN. Each successive element of + $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN are set to the drawn + ink and logical metrics of successive characters respectively, + relative to the drawing origin of the M-text. The number of + elements of $INK_ARRAY_RETURN and $LOGICAL_ARRAY_RETURN that have + been set is returned to $NUM_CHARS_RETURN. + + If $ARRAY_SIZE is too small to return all metrics, the function + returns -1 and store the requested size in $NUM_CHARS_RETURN. + Otherwise, it returns zero. + + If pointer $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN are not + @c NULL, this function also computes the metrics of the overall + text and stores the results in the members of the structure + pointed to by $OVERALL_INK_RETURN and $OVERALL_LOGICAL_RETURN. + + If $CONTROL->two_dimensional is nonzero, this function computes + only the metrics of characters in the first line. */ +/***ja + @brief M-text �γ�ʸ����ɽ���ϰϤ�׻�����. + + �ؿ� mdraw_text_per_char_extents () �ϡ��ؿ� mdraw_text_with_control () + ���������楪�֥������� $CONTROL ���Ѥ��� M-text $MT �� $FROM ���� $TO + �ޤǤ�ե졼�� $FRAME ��ɽ������ݤγ�ʸ���Υ�������׻����롣 + + $ARRAY_SIZE �ˤ�ä� $INK_ARRAY_RETURN ��$LOGICAL_ARRAY_RETURN + �Υ���������ꤹ�롣$INK_ARRAY_RETURN ��$LOGICAL_ARRAY_RETURN + �γ����Ǥϡ����줾��ʸ�������襤�󥯤�������������M-text + ��ɽ��������������а��͡ˤˤ�äƽ�������롣���ꤵ�줿 $INK_ARRAY_RETURN �� + $LOGICAL_ARRAY_RETURN �����Ǥο��ϡ�$NUM_CHARS_RETURN ���ᤵ��롣 + + $ARRAY_SIZE �����٤Ƥ���ˡ���᤻�ʤ��ۤɾ��������ˤϡ��ؿ��� -1 + ���֤���ɬ�פ��礭���� $NUM_CHARS_RETURN ���֤��������Ǥʤ���� 0 + ���֤��� + + �ݥ��� $OVERALL_INK_RETURN �� $OVERALL_LOGICAL_RETURN ��@c NULL + �Ǥʤ���С����δؿ��ϥƥ��������ΤΥ�������׻�������̤� + $OVERALL_INK_RETURN �� $OVERALL_LOGICAL_RETURN �ǻؤ���빽¤�Υ��Ф���¸���롣 + + $CONTROL->two_dimensional ��0�Ǥʤ���С����δؿ��Ϻǽ�ιԤ�ʸ���Υ�����������׻����롣 */ + +int +mdraw_text_per_char_extents (MFrame *frame, + MText *mt, int from, int to, + MDrawControl *control, + MDrawMetric *ink_array_return, + MDrawMetric *logical_array_return, + int array_size, + int *num_chars_return, + MDrawMetric *overall_ink_return, + MDrawMetric *overall_logical_return) +{ + MGlyphString *gstring; + MGlyph *g; + int x; + + ASSURE_CONTROL (control); + *num_chars_return = to - from; + if (array_size < *num_chars_return) + MERROR (MERROR_DRAW, -1); + if (overall_logical_return) + memset (overall_logical_return, 0, sizeof (MDrawMetric)); + if (overall_ink_return) + memset (overall_ink_return, 0, sizeof (MDrawMetric)); + + M_CHECK_RANGE (mt, from, to, -1, 0); + gstring = get_gstring (frame, mt, from, to, control); + if (! gstring) + { + *num_chars_return = 0; + return 0; + } + + for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++) + if (g->g.from >= from && g->g.from < to) + { + int start = g->g.from; + int end = g->g.to; + int width = g->g.xadv; + int lbearing = g->g.lbearing; + int rbearing = g->g.rbearing; + int ascent = g->g.ascent; + int descent = g->g.descent; + int logical_ascent; + int logical_descent; + + if (g->rface->rfont) + { + logical_ascent = g->rface->rfont->ascent; + logical_descent = g->rface->rfont->descent; + } + else + { + logical_ascent = g->rface->ascent; + logical_descent = g->rface->descent; + } + for (g++; g->type != GLYPH_ANCHOR && g->g.from == start; g++) + { + if (lbearing < width + g->g.lbearing) + lbearing = width + g->g.lbearing; + if (rbearing < width + g->g.rbearing) + rbearing = width + g->g.rbearing; + width += g->g.xadv; + if (ascent < g->g.ascent) + ascent = g->g.ascent; + if (descent < g->g.descent) + descent = g->g.descent; + } + + if (end > to) + end = to; + while (start < end) + { + if (ink_array_return) + { + ink_array_return[start - from].x = x + lbearing; + ink_array_return[start - from].y = - ascent; + ink_array_return[start - from].width = rbearing - lbearing; + ink_array_return[start - from].height = ascent + descent; + } + if (logical_array_return) + { + logical_array_return[start - from].x = x; + logical_array_return[start - from].y = - logical_descent; + logical_array_return[start - from].height + = logical_ascent + logical_descent; + logical_array_return[start - from].width = width; + } + start++; + } + x += width; + g--; + } + + if (overall_ink_return) + { + overall_ink_return->y = - gstring->line_ascent; + overall_ink_return->x = gstring->lbearing; + overall_ink_return->width = x - gstring->lbearing; + overall_ink_return->height = gstring->height; + } + if (overall_logical_return) + { + overall_logical_return->y = - gstring->ascent; + overall_logical_return->x = 0; + overall_logical_return->width = x; + overall_logical_return->height = gstring->ascent + gstring->descent; + } + + M17N_OBJECT_UNREF (gstring->top); + return 0; +} + +/*=*/ + +/***en + @brief Return the character position nearest to the coordinates. + + The mdraw_coordinates_position () function checks which character + is to be drawn at coordinate ($X, $Y) when the text between $FROM + and $TO of M-text $MT is drawn at the coordinate (0, 0) using the + mdraw_text_with_control () function with the drawing control + object $CONTROL. Here, the character position means the number of + characters that precede the character in question in $MT, that is, + the character position of the first character is 0. + + $FRAME is used only to get the default face information. + + @return + If the glyph image of a character covers coordinate ($X, $Y), + mdraw_coordinates_position () returns the character position of + that character.\n\n + If $Y is less than the minimum Y-coordinate of the drawn area, it + returns $FROM.\n\n + If $Y is greater than the maximum Y-coordinate of the drawn area, + it returns $TO.\n\n + If $Y fits in with the drawn area but $X is less than the minimum + X-coordinate, it returns the character position of the first + character drawn on the line $Y.\n\n + If $Y fits in with the drawn area but $X is greater than the + maximum X-coordinate, it returns the character position of the + last character drawn on the line $Y. */ + +/***ja + @brief ���ꤷ����ɸ�˺Ǥ�ᤤʸ����ʸ�����֤�����. + + �ؿ� mdraw_coordinates_position () �ϡ��ؿ� + mdraw_text_with_control () ���������楪�֥������� $CONTROL ���Ѥ��ơ� + M-text $MT �� $FROM ���� $TO �ޤǤ��ɸ (0, 0) + �����Ȥ������褹��ݤˡ���ɸ ($X, $Y) + �����褵���ʸ����ʸ�����֤��֤���������ʸ�����֤Ȥϡ����� + M-text ��ˤ����Ƥ���ʸ�����ǽ餫�鲿���ܤ��򼨤������Ǥ��롣�������ǽ��ʸ����ʸ�����֤�0�Ȥ��롣 + + $FRAME �ϥǥե���ȤΥե������ξ�������뤿��������Ѥ����롣 + + @return + ��ɸ ($X, $Y) ������ʸ���Υ���դ�ʤ�����硢 �ؿ� + mdraw_coordinates_position () �Ϥ���ʸ����ʸ�����֤��֤���\n\n + �⤷ $Y �������ΰ�κǾ�Y��ɸ���⾮�����ʤ�� $FROM ���֤���\n\n + �⤷ $Y �������ΰ�κ���Y��ɸ�����礭���ʤ�� $TO ���֤���\n\n + �⤷ $Y �������ΰ�˾�äƤ��Ƥ��� $X �������ΰ�κǾ�X��ɸ���� + ���������ϡ�ľ�� y = $Y ������褵���ǽ��ʸ����ʸ�����֤��֤���\n\n + �⤷ $Y �������ΰ�˾�äƤ��Ƥ��� $X �������ΰ�κ���X��ɸ���� + �礭�����ϡ�ľ�� y = $Y ������褵���Ǹ��ʸ����ʸ�����֤��֤��� */ + +int +mdraw_coordinates_position (MFrame *frame, MText *mt, int from, int to, + int x_offset, int y_offset, MDrawControl *control) +{ + MGlyphString *gstring; + int y = 0; + int width; + MGlyph *g; + + M_CHECK_POS_X (mt, from, -1); + if (to > mtext_nchars (mt) + (control->cursor_width != 0)) + to = mtext_nchars (mt) + (control->cursor_width != 0); + else if (to < from) + to = from; + + if (from == to) + return from; + ASSURE_CONTROL (control); + gstring = get_gstring (frame, mt, from, to, control); + while (y + gstring->line_descent <= y_offset + && gstring->to < to) + { + from = gstring->to; + y += gstring->line_descent; + M17N_OBJECT_UNREF (gstring->top); + gstring = get_gstring (frame, mt, from, to, control); + y += gstring->line_ascent; + } + + /* Accumulate width of glyphs in WIDTH until it exceeds X. */ + if (! control->orientation_reversed) + { + width = gstring->indent; + for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++) + if (g->g.from >= from && g->g.from < to) + { + width += g->g.xadv; + if (width > x_offset) + break; + } + } + else + { + width = - gstring->indent; + for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--) + if (g->g.from >= from && g->g.from < to) + { + width -= g->g.xadv; + if (width < x_offset) + break; + } + } + if (g->type == GLYPH_ANCHOR + && control->two_dimensional + && g[-1].g.c == '\n') + g--; + from = g->g.from; + M17N_OBJECT_UNREF (gstring->top); + + return from; +} + +/*=*/ + +/***en + @brief Compute information about a glyph. + + The mdraw_glyph_info () function computes information about a + glyph that covers a character at position $POS of the M-text $MT + assuming that the text is drawn from the character at $FROM of $MT + on a window of frame $FRAME using the mdraw_text_with_control () + function with the drawing control object $CONTROL. + + The information is stored in the members of $INFO. */ +/***ja + @brief ����դ˴ؤ�������׻�����. + + �ؿ� mdraw_glyph_info () �ϡ��ؿ� mdraw_text_with_control () + ���� �����楪�֥������� $CONTROL ���Ѥ���M-text $MT �� $FROM ���� $TO + �ޤǤ�ե졼�� $FRAME �����褷����硢M-text ��ʸ������ $POS + ��ʸ����ʤ������դ˴ؤ�������׻����롣 + + �����$INFO �Υ��Ф��ݻ�����롣 */ + +/*** + @seealso + MDrawGlyphInfo +*/ + +int +mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos, + MDrawControl *control, MDrawGlyphInfo *info) +{ + MGlyphString *gstring; + MGlyph *g; + int y = 0; + + M_CHECK_RANGE_X (mt, from, pos, -1); + + ASSURE_CONTROL (control); + gstring = get_gstring (frame, mt, from, pos + 1, control); + if (! gstring) + MERROR (MERROR_DRAW, -1); + while (gstring->to <= pos) + { + y += gstring->line_descent; + M17N_OBJECT_UNREF (gstring->top); + gstring = get_gstring (frame, mt, gstring->to, pos + 1, control); + y += gstring->line_ascent; + } + info->line_from = gstring->from; + if (info->line_from < from) + info->line_from = from; + info->line_to = gstring->to; + + info->y = y; + if (! control->orientation_reversed) + { + info->x = gstring->indent; + for (g = MGLYPH (1); g->g.from > pos || g->g.to <= pos; g++) + info->x += g->g.xadv; + } + else + { + info->x = - gstring->indent; + for (g = MGLYPH (gstring->used - 2); g->g.from > pos || g->g.to <= pos; g--) + info->x -= g->g.xadv; + while (g[-1].g.to == g->g.to) + g--; + } + info->from = g->g.from; + info->to = g->g.to; + info->metrics.x = g->g.lbearing; + info->metrics.y = - gstring->line_ascent; + info->metrics.height = gstring->height; + info->metrics.width = - g->g.lbearing + g->g.xadv; + if (g->rface->rfont) + info->font = (MFont *) g->rface->rfont; + else + info->font = NULL; + /* info->logical_width is calculated later. */ + + if (info->from > info->line_from) + { + /* The logically previous glyph is on this line. */ + MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1); + + info->prev_from = g_tmp->g.from; + } + else if (info->line_from > 0 + && gstring->from > 0) + { + /* The logically previous glyph is on the previous line. */ + MGlyphString *gst = get_gstring (frame, mt, gstring->from - 1, + gstring->from, control); + MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1); + + info->prev_from = g_tmp->g.from; + M17N_OBJECT_UNREF (gst->top); + } + else + info->prev_from = -1; + + if (GLYPH_INDEX (g) > 1) + info->left_from = g[-1].g.from, info->left_to = g[-1].g.to; + else if (! control->orientation_reversed) + { + if (info->line_from > 0) + { + MGlyph *g_tmp; + MGlyphString *gst; + int p = gstring->from - 1; + + gst = get_gstring (frame, mt, p, gstring->from, control); + g_tmp = gst->glyphs + (gst->used - 2); + info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to; + M17N_OBJECT_UNREF (gst->top); + } + else + info->left_from = info->left_to = -1; + } + else + { + if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt)) + { + MGlyph *g_tmp; + MGlyphString *gst; + int p = gstring->to; + + gst = get_gstring (frame, mt, p, p + 1, control); + g_tmp = gst->glyphs + (gst->used - 2); + info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to; + M17N_OBJECT_UNREF (gst->top); + } + else + info->left_from = info->left_to = -1; + } + + if (info->to < gstring->to) + { + /* The logically next glyph is on this line. */ + MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0); + + info->next_to = g_tmp->g.to; + } + else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt)) + { + /* The logically next glyph is on the next line. */ + int p = info->to; + MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control); + MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0); + + info->next_to = g_tmp->g.to; + M17N_OBJECT_UNREF (gst->top); + } + else + info->next_to = -1; + + for (info->logical_width = (g++)->g.xadv; + g->g.from == pos && g->type != GLYPH_ANCHOR; + info->metrics.width += g->g.xadv, info->logical_width += (g++)->g.xadv); + info->metrics.width += g[-1].g.rbearing - g[-1].g.xadv; + + if (g->type != GLYPH_ANCHOR) + info->right_from = g->g.from, info->right_to = g->g.to; + else if (! control->orientation_reversed) + { + if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt)) + { + pos = gstring->to; + M17N_OBJECT_UNREF (gstring->top); + gstring = get_gstring (frame, mt, pos, pos + 1, control); + g = MGLYPH (1); + info->right_from = g->g.from, info->right_to = g->g.to; + } + else + info->right_from = info->right_to = -1; + } + else + { + if (info->line_from > 0) + { + pos = gstring->from - 1; + M17N_OBJECT_UNREF (gstring->top); + gstring = get_gstring (frame, mt, pos, pos + 1, control); + g = MGLYPH (1); + info->right_from = g->g.from, info->right_to = g->g.to; + } + else + info->right_from = info->right_to = -1; + } + + M17N_OBJECT_UNREF (gstring->top); + return 0; +} + +/*=*/ + +/***en + @brief Compute information about glyph sequence. + + The mdraw_glyph_list () function computes information about glyphs + corresponding to the text between $FROM and $TO of M-text $MT when + it is drawn on a window of frame $FRAME using the + mdraw_text_with_control () function with the drawing control + object $CONTROL. $GLYPHS is an array of objects to store the + information, and $ARRAY_SIZE is the array size. + + If $ARRAY_SIZE is large enough to cover all glyphs, it stores the + number of actually filled elements in the place pointed by + $NUM_GLYPHS_RETURN, and returns 0. + + Otherwise, it stores the required array size in the place pointed + by $NUM_GLYPHS_RETURN, and returns -1. */ + +/***ja + @brief �������˴ؤ�������׻�����. + + �ؿ� mdraw_glyph_list () �ϡ��ؿ� mdraw_text_with_control () + ���������楪�֥������� $CONTROL ���Ѥ���M-text $MT �� $FROM ���� $TO + �ޤǤ�ե졼�� $FRAME �����褷�����Ρ��ƥ���դξ���� $GLYPHS + ���ؤ�����˳�Ǽ���롣 $ARRAY_SIZE �Ϥ�������Υ������Ǥ��롣 + + �⤷ $ARRAY_SIZE �����٤ƤΥ���դˤĤ��Ƥξ�����Ǽ����Τ˽�ʬ�Ǥ���С� + $NUM_GLYPHS_RETURN ���ؤ����˼ºݤ���᤿���Ǥο������ꤷ 0 ���֤��� + + + �����Ǥʤ���С�$NUM_GLYPHS_RETURN ���ؤ�����ɬ�פ�����Υ����������ꤷ�� + -1 ���֤��� + */ + +/*** + @seealso + MDrawGlyph +*/ + +int +mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to, + MDrawControl *control, MDrawGlyph *glyphs, + int array_size, int *num_glyphs_return) +{ + MGlyphString *gstring; + MGlyph *g; + int n; + int pad_width = 0; + + ASSURE_CONTROL (control); + *num_glyphs_return = 0; + M_CHECK_RANGE (mt, from, to, -1, 0); + gstring = get_gstring (frame, mt, from, to, control); + if (! gstring) + return -1; + for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++) + { + if (g->type == GLYPH_BOX + || g->g.from < from || g->g.from >= to) + continue; + if (g->type == GLYPH_PAD) + { + if (g->left_padding) + pad_width = g->g.xadv; + else if (n > 0) + { + pad_width = 0; + glyphs[-1].x_advance += g->g.xadv; + } + continue; + } + if (n < array_size) + { + glyphs->from = g->g.from; + glyphs->to = g->g.to; + glyphs->glyph_code = g->g.code; + glyphs->x_off = g->g.xoff + pad_width; + glyphs->y_off = g->g.yoff; + glyphs->lbearing = g->g.lbearing; + glyphs->rbearing = g->g.rbearing; + glyphs->ascent = g->g.ascent; + glyphs->descent = g->g.descent; + glyphs->x_advance = g->g.xadv + pad_width; + glyphs->y_advance = 0; + if (g->rface->rfont) + { + glyphs->font = (MFont *) g->rface->rfont; +#ifdef HAVE_FREETYPE + glyphs->font_type + = (glyphs->font->source == MFONT_SOURCE_X ? Mx + : g->rface->rfont->driver == &mfont__ft_driver ? Mfreetype + : Mxft); +#else /* not HAVE_FREETYPE */ + glyphs->font_type = Mx; +#endif /* not HAVE_FREETYPE */ + glyphs->fontp = g->rface->rfont->fontp; + } + else + { + glyphs->font = NULL; + glyphs->font_type = Mnil; + glyphs->fontp = NULL; + } + pad_width = 0; + glyphs++; + } + n++; + } + M17N_OBJECT_UNREF (gstring->top); + + *num_glyphs_return = n; + return (n <= array_size ? 0 : -1); +} + +/*=*/ + +/***en + @brief Draw one or more textitems. + + The mdraw_text_items () function draws one or more M-texts on + window $WIN of frame $FRAME at coordinate ($X, $Y). $ITEMS is an array + of the textitems to be drawn and $NITEMS is the number of + textitems in the array. */ + +/***ja + @brief textitem ��ɽ������. + + �ؿ� mdraw_text_items () �ϡ���İʾ�Υƥ����ȥ����ƥ�򡢥ե졼�� + $FRAME �Υ�����ɥ� $WIN �κ�ɸ ($X, $Y) ��ɽ�����롣$ITEMS + ��ɽ�����٤��ƥ����ȥ����ƥ������Ǥ��ꡢ$NITEMS �Ϥ��θĿ��Ǥ��롣 + + @latexonly \IPAlabel{mdraw_text_items} @endlatexonly */ + +/*** + @seealso + MTextItem, mdraw_text (). */ + +void +mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y, + MDrawTextItem *items, int nitems) +{ + if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT)) + return; + while (nitems-- > 0) + { + if (items->face) + mtext_push_prop (items->mt, 0, mtext_nchars (items->mt), Mface, + items->face); + mdraw_text_with_control (frame, win, x, y, + items->mt, 0, mtext_nchars (items->mt), + items->control); + x += mdraw_text_extents (frame, items->mt, 0, mtext_nchars (items->mt), + items->control, NULL, NULL, NULL); + x += items->delta; + if (items->face) + mtext_pop_prop (items->mt, 0, mtext_nchars (items->mt), Mface); + } +} + +/*=*/ +/***en + @brief Option of line breaking for drawing text. + + The variable #mdraw_line_break_option specifies line breaking + options by logical-or of the members of #MTextLineBreakOption. It + controls the line breaking algorithm of the function + mdraw_default_line_break (). */ + +int mdraw_line_break_option; + +/*=*/ +/***en + @brief Calculate a line breaking position. + + The function mdraw_default_line_break () calculates a line + breaking position based on the line number $LINE and the + coordinate $Y, when a line is too long to fit within the width + limit. $POS is the position of the character next to the last one + that fits within the limit. $FROM is the position of the first + character of the line, and $TO is the position of the last + character displayed on the line if there were not width limit. + $LINE and $Y are reset to 0 when a line is broken by a newline + character, and incremented each time when a long line is broken + because of the width limit. + + @return + This function returns a character position to break the + line. +*/ + +/***ja + @brief ���԰��֤�׻�����. + + �ؿ� mdraw_default_line_break () �ϡ��Ԥ���������˼��ޤ�ʤ����β��԰��֤򡢹��ֹ� + $LINE �Ⱥ�ɸ $Y �˴�Ť��Ʒ׻����롣 + $POS �Ϻ������˼��ޤ�Ǹ��ʸ���μ���ʸ���ΰ��֤Ǥ��롣 + $FROM �Ϥ��ιԤκǽ��ʸ���ΰ��֡�$TO + �Ϻ����������ꤵ��Ƥ��ʤ���Ф��ιԤ�ɽ�������Ǹ��ʸ���ΰ��֤Ǥ��롣 + $LINE �� $Y �ϲ���ʸ���ˤ�äƹԤ����ޤä��ݤˤ� 0 + �˥ꥻ�åȤ��졢�������ˤ�äƹԤ����ޤä����ˤ� 1 �Ť����䤵��롣 + + @return + ���δؿ��ϲ��Ԥ���ʸ�����֤��֤��� +*/ + +int +mdraw_default_line_break (MText *mt, int pos, + int from, int to, int line, int y) +{ + int p, after; + + p = mtext_line_break (mt, pos, mdraw_line_break_option, &after); + if (p < from) + p = from; + else if (p >= to) + p = to; + return p; +} + +/*=*/ + +/***en + @brief Obtain per character dimension information. + + The mdraw_per_char_extents () function computes the text dimension + of each character in M-text $MT. The faces given as text + properties in $MT and the default face of frame $FRAME determine + the fonts to draw the text. Each successive element in + $ARRAY_RETURN is set to the drawn metrics of successive + characters, which is relative to the origin of the drawing, and a + rectangle for each character in $MT. The number of elements of + $ARRAY_RETURN must be equal to or greater than the number of + characters in $MT. + + If pointer $OVERALL_RETURN is not @c NULL, this function also + computes the extents of the overall text and stores the results in + the members of the structure pointed to by $OVERALL_RETURN. */ + +/***ja + @brief M-text ��ʸ�����ɽ���ϰϾ��������. + + �ؿ� mdraw_per_char_extents () �ϡ�M-text $MT + ��γ�ʸ����ɽ���ϰϤ�׻����롣���η׻����Ѥ���ե���Ȥϡ� + $MT �Υƥ����ȥץ��ѥƥ��ǻ��ꤵ�줿�ե������ȡ��ե졼�� $FRAME + �Υǥե���ȥե������ˤ�äƷ�ޤ롣$ARRAY_RETURN �γ����Ǥϡ�$MT + ��γ�ʸ����ɽ���ϰϾ���ˤ�äƽ�������롣ɽ���ϰϾ���Ȥϡ� + ɽ��������������а��֤ȳ�ʸ��������Ĺ�����Ǥ��롣$ARRAY_RETURN + �����ǿ��ϡ�M-text ���ʸ�����ʾ�Ǥʤ���Фʤ�ʤ��� + + �ݥ��� $OVERALL_RETURN �� @c NULL + �Ǥʤ����ϡ��ƥ��������Τ�ɽ���ϰϾ����׻��������η�̤� + $OVERALL_RETURN �λؤ���¤�Τ˳�Ǽ���롣 + + @latexonly \IPAlabel{mdraw_per_char_extents} @endlatexonly */ + +void +mdraw_per_char_extents (MFrame *frame, MText *mt, + MDrawMetric *array_return, + MDrawMetric *overall_return) +{ + int n = mtext_nchars (mt); + + mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL, + n, &n, overall_return, NULL); +} + +/***en + @brief clear cached information. + + The mdraw_clear_cache () function clear cached information + on M-text $MT that was attached by any of the drawing functions. + When the behavior of `format' or `line_break' + member functions of MDrawControl is changed, the cache must be cleared. + + @seealso + MDrawControl */ +/***ja + @brief ����å�������ä�. + + �ؿ� mdraw_clear_cache () ������ؿ��ˤ�ä� M-text $MT + ���ղä��줿����å������򤹤٤ƾõ�롣MDrawControl �� `format' + ���뤤�� `line_break' + ���дؿ��ο��񤤤��Ѥ�ä����ˤϥ���å����õ�ʤ��ƤϤʤ�ʤ��� + + @seealso + MDrawControl */ + +void +mdraw_clear_cache (MText *mt) +{ + mtext_pop_prop (mt, 0, mtext_nchars (mt), M_glyph_string); +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/face.c b/src/face.c new file mode 100644 index 0000000..33751e5 --- /dev/null +++ b/src/face.c @@ -0,0 +1,2101 @@ +/* face.c -- face module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nFace + @brief A face is an object to control appearance of M-text. + + A @e face is an object of the type #MFace and controls how to + draw M-texts. A face has a fixed number of @e face @e properties. + Like other types of properties, a face property consists of a key + and a value. A key is one of the following symbols: + + #Mforeground, #Mbackground, #Mvideomode, #Mhline, #Mbox, + #Mfoundry, #Mfamily, #Mweight, #Mstyle, #Mstretch, #Madstyle, + #Msize, #Mfontset, #Mratio, #Mhook_func, #Mhook_arg + + The notation "xxx property of F" means the face property that + belongs to face F and whose key is @c Mxxx. + + The M-text drawing functions first search an M-text for the text + property whose key is the symbol #Mface, then draw the M-text + using the value of that text property. This value must be a + pointer to a face object. + + If there are multiple text properties whose key is @c Mface, and + they are not conflicting one another, properties of those faces + are merged and used. + + If no faces specify a certain property, the value of the default + face is used. */ + +/***ja + @addtogroup m17nFace + @brief �ե������Ȥϡ�M-text �θ��ɤ������椹�륪�֥������ȤǤ���. + + @e �ե����� �� #MFace ���Υ��֥������ȤǤ��ꡢM-text + ��ɽ����ˡ�����椹�롣�ե������ϸ���Ĥ� @e �ե������ץ��ѥƥ� ����ġ� + ¾�Υץ��ѥƥ�Ʊ�ͥե������ץ��ѥƥ��ϥ������ͤ���ʤꡢ�����ϰʲ��Υ���ܥ�Τ����줫�Ǥ��롣 + + #Mforeground, #Mbackground, #Mvideomode, #Mhline, #Mbox, + #Mfoundry, #Mfamily, #Mweight, #Mstyle, #Mstretch, #Madstyle, + #Msize, #Mfontset, #Mratio, #Mhook_func, #Mhook_arg + + �֥ե����� F �Υե������ץ��ѥƥ��Τ��������� @c Mxxx + �Ǥ����ΡפΤ��Ȥ��ñ�ˡ�F �� xxx �ץ��ѥƥ��פȸƤ֤��Ȥ����롣 + + M-text ��ɽ���ؿ��ϡ��ޤ��ǽ�ˤ��� M-text ���饭��������ܥ� + #Mface �Ǥ���褦�ʥƥ����ȥץ��ѥƥ���õ�������ˤ����ͤ˽��ä� + M-text ��ɽ�����롣�����ͤϥե��������֥������ȤؤΥݥ��󥿤Ǥʤ���Фʤ�ʤ��� + + M-text ����#Mface + �򥭡��Ȥ���ƥ����ȥץ��ѥƥ���ʣ�����äƤ��ꡢ���Ĥ������ͤ����ͤ��ʤ��ʤ�С��ե�����������Ȥ߹�蘆����Ѥ����롣 + + ����ƥ�����°�����ɤΥե������ˤ�äƤ���ꤵ��Ƥ��ʤ����ϡ��ǥե���ȥե��������ͤ��Ѥ����롣 */ + +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include +#include + +#include "config.h" +#include "m17n-gui.h" +#include "m17n-misc.h" +#include "internal.h" +#include "charset.h" +#include "symbol.h" +#include "plist.h" +#include "mtext.h" +#include "textprop.h" +#include "internal-gui.h" +#include "face.h" +#include "font.h" +#include "fontset.h" + +static M17NObjectArray face_table; + +MSymbol Mlatin; + +static MSymbol M_face_prop_index; + +static MPlist *hline_prop_list; +static MPlist *box_prop_list; + +/** Special hook function pointer that does nothing. */ +static MFaceHookFunc noop_hook; + +/** */ +static MFaceHLineProp * +get_hline_create (MFaceHLineProp *prop) +{ + MPlist *plist; + MFaceHLineProp *hline; + + if (prop->width == 0) + return MPLIST_VAL (hline_prop_list); + MPLIST_DO (plist, MPLIST_NEXT (hline_prop_list)) + { + hline = MPLIST_VAL (plist); + if (prop->type == hline->type + && prop->width == hline->width + && prop->color == hline->color) + return hline; + } + MSTRUCT_MALLOC (hline, MERROR_FACE); + *hline = *prop; + mplist_push (plist, Mt, hline); + return hline; +} + +static MFaceBoxProp * +get_box_create (MFaceBoxProp *prop) +{ + MPlist *plist; + MFaceBoxProp *box; + + if (prop->width == 0) + return MPLIST_VAL (box_prop_list); + MPLIST_DO (plist, MPLIST_NEXT (box_prop_list)) + { + box = MPLIST_VAL (plist); + if (prop->width == box->width + && prop->color_top == box->color_top + && prop->color_bottom == box->color_bottom + && prop->color_left == box->color_left + && prop->color_right == box->color_right + && prop->inner_hmargin == box->inner_hmargin + && prop->inner_vmargin == box->inner_vmargin + && prop->outer_hmargin == box->inner_hmargin + && prop->inner_vmargin == box->inner_vmargin) + return box; + } + MSTRUCT_MALLOC (box, MERROR_FACE); + *box = *prop; + mplist_push (plist, Mt, box); + return box; +} + +/** From FRAME->realized_face_list, find a realized face based on + FACE. */ + +static MRealizedFace * +find_realized_face (MFrame *frame, MFace *face, MFont *font) +{ + MPlist *plist; + + MPLIST_DO (plist, frame->realized_face_list) + { + MRealizedFace *rface = MPLIST_VAL (plist); + + if (memcmp (rface->face.property, face->property, + sizeof face->property) == 0 + && (rface->font + ? (font && ! memcmp (rface->font, font, sizeof (MFont))) + : ! font)) + return rface; + } + return NULL; +} + +static void +free_face (void *object) +{ + MFace *face = (MFace *) object; + + if (face->property[MFACE_FONTSET]) + M17N_OBJECT_UNREF (face->property[MFACE_FONTSET]); + M17N_OBJECT_UNREF (face->frame_list); + M17N_OBJECT_UNREGISTER (face_table, face); + free (object); +} + + +static MPlist * +serialize_hline (MPlist *plist, MFaceHLineProp *hline) +{ + if (hline->width > 0) + { + MPlist *pl = mplist (); + + mplist_add (pl, Minteger, (void *) hline->type); + mplist_add (pl, Minteger, (void *) hline->width); + mplist_add (pl, Msymbol, hline->color); + plist = mplist_add (plist, Mplist, pl); + M17N_OBJECT_UNREF (pl); + } + return plist; +} + +static MPlist * +serialize_box (MPlist *plist, MFaceBoxProp *box) +{ + if (box->width > 0) + { + MPlist *pl = mplist (); + + mplist_add (pl, Minteger, (void *) box->width); + mplist_add (pl, Minteger, (void *) box->inner_hmargin); + mplist_add (pl, Minteger, (void *) box->inner_vmargin); + mplist_add (pl, Minteger, (void *) box->outer_hmargin); + mplist_add (pl, Minteger, (void *) box->outer_vmargin); + mplist_add (pl, Msymbol, box->color_top); + mplist_add (pl, Msymbol, box->color_bottom); + mplist_add (pl, Msymbol, box->color_left); + mplist_add (pl, Msymbol, box->color_right); + plist = mplist_add (plist, Mplist, pl); + M17N_OBJECT_UNREF (pl); + } + return plist; +} + +static MPlist * +serialize_face (void *val) +{ + MFace *face = val; + MPlist *plist = mplist (), *pl = plist; + int i; + struct { + MSymbol *key; + MSymbol *type; + MPlist *(*func) (MPlist *plist, void *val); + } serializer[MFACE_RATIO + 1] + = { { &Mfoundry, &Msymbol }, + { &Mfamily, &Msymbol }, + { &Mweight, &Msymbol }, + { &Mstyle, &Msymbol }, + { &Mstretch, &Msymbol }, + { &Madstyle, &Msymbol }, + { &Msize, &Minteger }, + { &Mfontset, NULL }, + { &Mforeground, &Msymbol }, + { &Mbackground, &Msymbol }, + { &Mhline, NULL }, + { &Mbox, NULL }, + { &Mvideomode, &Msymbol }, + { &Mratio, &Minteger } }; + + for (i = 0; i <= MFACE_RATIO; i++) + if (face->property[i] && serializer[i].key) + { + pl = mplist_add (pl, Msymbol, *serializer[i].key); + if (serializer[i].type) + pl = mplist_add (pl, *serializer[i].type, face->property[i]); + else if (i == MFACE_FONTSET) + pl = mplist_add (pl, Msymbol, mfontset_name ((MFontset *) + face->property[i])); + else if (i == MFACE_HLINE) + pl = serialize_hline (pl, (MFaceHLineProp *) face->property[i]); + else if (i == MFACE_BOX) + pl = serialize_box (pl, (MFaceBoxProp *) face->property[i]); + } + + return plist; +} + +static void * +deserialize_hline (MPlist *plist) +{ + MFaceHLineProp hline, *hline_ret; + + if (! MPLIST_INTEGER_P (plist)) + MERROR (MERROR_FACE, NULL); + hline.type = MPLIST_INTEGER_P (plist); + plist = MPLIST_NEXT (plist); + if (! MPLIST_INTEGER_P (plist)) + MERROR (MERROR_FACE, NULL); + hline.width = MPLIST_INTEGER_P (plist); + plist = MPLIST_NEXT (plist); + if (! MPLIST_SYMBOL_P (plist)) + MERROR (MERROR_FACE, NULL); + hline.color = MPLIST_SYMBOL (plist); + MSTRUCT_MALLOC (hline_ret, MERROR_FACE); + *hline_ret = hline; + return hline_ret; +} + +static void * +deserialize_box (MPlist *plist) +{ + MFaceBoxProp box, *box_ret; + + if (! MPLIST_INTEGER_P (plist)) + MERROR (MERROR_FACE, NULL); + box.width = MPLIST_INTEGER (plist); + plist = MPLIST_NEXT (plist); + if (! MPLIST_INTEGER_P (plist)) + MERROR (MERROR_FACE, NULL); + box.inner_hmargin = MPLIST_INTEGER (plist); + plist = MPLIST_NEXT (plist); + if (! MPLIST_INTEGER_P (plist)) + MERROR (MERROR_FACE, NULL); + box.inner_vmargin = MPLIST_INTEGER (plist); + plist = MPLIST_NEXT (plist); + if (! MPLIST_INTEGER_P (plist)) + MERROR (MERROR_FACE, NULL); + box.outer_hmargin = MPLIST_INTEGER (plist); + plist = MPLIST_NEXT (plist); + if (! MPLIST_INTEGER_P (plist)) + MERROR (MERROR_FACE, NULL); + box.outer_vmargin = MPLIST_INTEGER (plist); + plist = MPLIST_NEXT (plist); + if (! MPLIST_SYMBOL_P (plist)) + MERROR (MERROR_FACE, NULL); + box.color_top = MPLIST_SYMBOL (plist); + plist = MPLIST_NEXT (plist); + if (! MPLIST_SYMBOL_P (plist)) + MERROR (MERROR_FACE, NULL); + box.color_bottom = MPLIST_SYMBOL (plist); + plist = MPLIST_NEXT (plist); + if (! MPLIST_SYMBOL_P (plist)) + MERROR (MERROR_FACE, NULL); + box.color_left = MPLIST_SYMBOL (plist); + plist = MPLIST_NEXT (plist); + if (! MPLIST_SYMBOL_P (plist)) + MERROR (MERROR_FACE, NULL); + box.color_right = MPLIST_SYMBOL (plist); + MSTRUCT_MALLOC (box_ret, MERROR_FACE); + *box_ret = box; + return box_ret; +} + +static void * +deserialize_face (MPlist *plist) +{ + MFace *face = mface (); + + MPLIST_DO (plist, plist) + { + MSymbol key; + int index; + void *val; + + if (! MPLIST_SYMBOL_P (plist)) + break; + key = MPLIST_SYMBOL (plist); + index = (int) msymbol_get (key, M_face_prop_index) - 1; + plist = MPLIST_NEXT (plist); + if (MPLIST_TAIL_P (plist)) + break; + if (index < 0 || index > MFACE_RATIO) + continue; + if (key == Mfoundry || key == Mfamily || key == Mweight || key == Mstyle + || key == Mstretch || key == Madstyle + || key == Mforeground || key == Mbackground || key == Mvideomode) + { + if (! MPLIST_SYMBOL_P (plist)) + continue; + val = MPLIST_VAL (plist); + } + else if (key == Msize || key == Mratio) + { + if (! MPLIST_INTEGER_P (plist)) + continue; + val = MPLIST_VAL (plist); + } + else if (key == Mfontset) + { + if (! MPLIST_SYMBOL_P (plist)) + continue; + val = mfontset (MSYMBOL_NAME (MPLIST_SYMBOL (plist))); + } + else if (key == Mhline) + { + if (! MPLIST_PLIST_P (plist)) + continue; + val = deserialize_hline (MPLIST_PLIST (plist)); + } + else if (key == Mbox) + { + if (! MPLIST_PLIST_P (plist)) + continue; + val = deserialize_box (MPLIST_PLIST (plist)); + } + face->property[index] = val; + } + return face; +} + +static MGlyphString work_gstring; + + + +/* Internal API */ + +MFace *mface__default; + +int +mface__init () +{ + int i; + MFaceHLineProp *hline; + MFaceBoxProp *box; + + M17N_OBJECT_ADD_ARRAY (face_table, "Face"); + Mface = msymbol_as_managing_key (" face"); + msymbol_put_func (Mface, Mtext_prop_serializer, + M17N_FUNC (serialize_face)); + msymbol_put_func (Mface, Mtext_prop_deserializer, + M17N_FUNC (deserialize_face)); + + Mforeground = msymbol ("foreground"); + Mbackground = msymbol ("background"); + Mvideomode = msymbol ("videomode"); + Mnormal = msymbol ("normal"); + Mreverse = msymbol ("reverse"); + Mratio = msymbol ("ratio"); + Mhline = msymbol ("hline"); + Mbox = msymbol ("box"); + Mhook_func = msymbol ("hook-func"); + Mhook_arg = msymbol ("hook-arg"); + + Mlatin = msymbol ("latin"); + M_face_prop_index = msymbol (" face-prop-index"); + + { + struct { + /* Pointer to the key symbol of the face property. */ + MSymbol *key; + /* Index (enum face_property) of the face property. */ + int index; + } mface_prop_data[MFACE_HOOK_ARG + 1] = + { { &Mfoundry, MFACE_FOUNDRY }, + { &Mfamily, MFACE_FAMILY }, + { &Mweight, MFACE_WEIGHT }, + { &Mstyle, MFACE_STYLE }, + { &Mstretch, MFACE_STRETCH }, + { &Madstyle, MFACE_ADSTYLE }, + { &Msize, MFACE_SIZE }, + { &Mfontset, MFACE_FONTSET }, + { &Mforeground, MFACE_FOREGROUND }, + { &Mbackground, MFACE_BACKGROUND }, + { &Mhline, MFACE_HLINE }, + { &Mbox, MFACE_BOX }, + { &Mvideomode, MFACE_VIDEOMODE }, + { &Mratio, MFACE_RATIO }, + { &Mhook_arg, MFACE_HOOK_ARG } }; + + for (i = 0; i < MFACE_PROPERTY_MAX; i++) + /* We add one to distinguish it from no-property. */ + msymbol_put (*mface_prop_data[i].key, M_face_prop_index, + (void *) (mface_prop_data[i].index + 1)); + } + + hline_prop_list = mplist (); + MSTRUCT_CALLOC (hline, MERROR_FACE); + mplist_push (hline_prop_list, Mt, hline); + box_prop_list = mplist (); + MSTRUCT_CALLOC (box, MERROR_FACE); + mplist_push (box_prop_list, Mt, box); + + mface__default = mface (); + mface__default->property[MFACE_FOUNDRY] = msymbol ("misc"); + mface__default->property[MFACE_FAMILY] = msymbol ("fixed"); + mface__default->property[MFACE_WEIGHT] = msymbol ("medium"); + mface__default->property[MFACE_STYLE] = msymbol ("r"); + mface__default->property[MFACE_STRETCH] = msymbol ("normal"); + mface__default->property[MFACE_ADSTYLE] = msymbol (""); + mface__default->property[MFACE_SIZE] = (void *) 120; + mface__default->property[MFACE_FONTSET] = mfontset (NULL); + mface__default->property[MFACE_FOREGROUND] = msymbol ("black"); + mface__default->property[MFACE_BACKGROUND] = msymbol ("white"); + mface__default->property[MFACE_HLINE] = hline; + mface__default->property[MFACE_BOX] = box; + mface__default->property[MFACE_VIDEOMODE] = Mnormal; + mface__default->hook = noop_hook; + + mface_normal_video = mface (); + mface_normal_video->property[MFACE_VIDEOMODE] = (void *) Mnormal; + + mface_reverse_video = mface (); + mface_reverse_video->property[MFACE_VIDEOMODE] = (void *) Mreverse; + + { + MFaceHLineProp hline_prop; + + hline_prop.type = MFACE_HLINE_UNDER; + hline_prop.width = 1; + hline_prop.color = Mnil; + mface_underline = mface (); + mface_put_prop (mface_underline, Mhline, &hline_prop); + } + + mface_medium = mface (); + mface_medium->property[MFACE_WEIGHT] = (void *) msymbol ("medium"); + mface_bold = mface (); + mface_bold->property[MFACE_WEIGHT] = (void *) msymbol ("bold"); + mface_italic = mface (); + mface_italic->property[MFACE_STYLE] = (void *) msymbol ("i"); + mface_bold_italic = mface_copy (mface_bold); + mface_bold_italic->property[MFACE_STYLE] + = mface_italic->property[MFACE_STYLE]; + + mface_xx_small = mface (); + mface_xx_small->property[MFACE_RATIO] = (void *) 50; + mface_x_small = mface (); + mface_x_small->property[MFACE_RATIO] = (void *) 67; + mface_small = mface (); + mface_small->property[MFACE_RATIO] = (void *) 75; + mface_normalsize = mface (); + mface_normalsize->property[MFACE_RATIO] = (void *) 100; + mface_large = mface (); + mface_large->property[MFACE_RATIO] = (void *) 120; + mface_x_large = mface (); + mface_x_large->property[MFACE_RATIO] = (void *) 150; + mface_xx_large = mface (); + mface_xx_large->property[MFACE_RATIO] = (void *) 200; + + mface_black = mface (); + mface_black->property[MFACE_FOREGROUND] = (void *) msymbol ("black"); + mface_white = mface (); + mface_white->property[MFACE_FOREGROUND] = (void *) msymbol ("white"); + mface_red = mface (); + mface_red->property[MFACE_FOREGROUND] = (void *) msymbol ("red"); + mface_green = mface (); + mface_green->property[MFACE_FOREGROUND] = (void *) msymbol ("green"); + mface_blue = mface (); + mface_blue->property[MFACE_FOREGROUND] = (void *) msymbol ("blue"); + mface_cyan = mface (); + mface_cyan->property[MFACE_FOREGROUND] = (void *) msymbol ("cyan"); + mface_yellow = mface (); + mface_yellow->property[MFACE_FOREGROUND] = (void *) msymbol ("yellow"); + mface_magenta = mface (); + mface_magenta->property[MFACE_FOREGROUND] = (void *) msymbol ("magenta"); + + work_gstring.glyphs = malloc (sizeof (MGlyph) * 2); + work_gstring.size = 2; + work_gstring.used = 0; + work_gstring.inc = 1; + return 0; +} + +void +mface__fini () +{ + MPlist *plist; + + M17N_OBJECT_UNREF (mface__default); + M17N_OBJECT_UNREF (mface_normal_video); + M17N_OBJECT_UNREF (mface_reverse_video); + M17N_OBJECT_UNREF (mface_underline); + M17N_OBJECT_UNREF (mface_medium); + M17N_OBJECT_UNREF (mface_bold); + M17N_OBJECT_UNREF (mface_italic); + M17N_OBJECT_UNREF (mface_bold_italic); + M17N_OBJECT_UNREF (mface_xx_small); + M17N_OBJECT_UNREF (mface_x_small); + M17N_OBJECT_UNREF (mface_small); + M17N_OBJECT_UNREF (mface_normalsize); + M17N_OBJECT_UNREF (mface_large); + M17N_OBJECT_UNREF (mface_x_large); + M17N_OBJECT_UNREF (mface_xx_large); + M17N_OBJECT_UNREF (mface_black); + M17N_OBJECT_UNREF (mface_white); + M17N_OBJECT_UNREF (mface_red); + M17N_OBJECT_UNREF (mface_green); + M17N_OBJECT_UNREF (mface_blue); + M17N_OBJECT_UNREF (mface_cyan); + M17N_OBJECT_UNREF (mface_yellow); + M17N_OBJECT_UNREF (mface_magenta); + + MPLIST_DO (plist, hline_prop_list) + free (MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (hline_prop_list); + MPLIST_DO (plist, box_prop_list) + free (MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (box_prop_list); + + free (work_gstring.glyphs); +} + +/** Return a face realized from NUM number of base faces pointed by + FACES on the frame FRAME. If SIZE is nonzero, it specifies the + maximum font size. */ + +MRealizedFace * +mface__realize (MFrame *frame, MFace **faces, int num, int size, MFont *font) +{ + MRealizedFace *rface; + MRealizedFont *rfont; + MFace merged_face = *(frame->face); + int i, j; + MFaceHookFunc func; + MFont spec; + + if (num == 0 && frame->rface && ! font) + return frame->rface; + + if (! mplist_find_by_value (frame->face->frame_list, frame)) + mplist_push (frame->face->frame_list, Mt, frame); + for (i = 0; i < num; i++) + if (! mplist_find_by_value (faces[i]->frame_list, frame)) + mplist_push (faces[i]->frame_list, Mt, frame); + + for (i = 0; i < MFACE_PROPERTY_MAX; i++) + for (j = num - 1; j >= 0; j--) + if (faces[j]->property[i]) + { + merged_face.property[i] = faces[j]->property[i]; + break; + } + + if (font) + { + if (font->type != MFONT_TYPE_REALIZED) + font = mfont_copy (font); + for (i = 0; i <= MFACE_ADSTYLE; i++) + if (font->property[i]) + merged_face.property[i] = FONT_PROPERTY (font, i); + if (font->size) + { + int font_size; + + if (font->size < 0) + font->size = ((double) (- font->size)) * frame->dpi / 72.27 + 0.5; + font_size = font->size; + merged_face.property[MFACE_SIZE] = (void *) font_size; + merged_face.property[MFACE_RATIO] = (void *) 0; + } + } + + if (! font || ! font->size) + { + double font_size = (int) merged_face.property[MFACE_SIZE]; + int ifont_size; + + if (font_size < 0) + font_size = - font_size * frame->dpi / 72.27; + if (merged_face.property[MFACE_RATIO] + && (int) merged_face.property[MFACE_RATIO] != 100) + { + font_size *= (int) merged_face.property[MFACE_RATIO]; + font_size /= 100; + } + ifont_size = font_size + 0.5; + merged_face.property[MFACE_SIZE] = (void *) ifont_size; + merged_face.property[MFACE_RATIO] = (void *) 0; + } + + merged_face.property[MFACE_FOUNDRY] = Mnil; + rface = find_realized_face (frame, &merged_face, font); + if (rface) + { + if (font && font->type != MFONT_TYPE_REALIZED) + free (font); + return rface; + } + + MSTRUCT_CALLOC (rface, MERROR_FACE); + mplist_push (frame->realized_face_list, Mt, rface); + rface->frame = frame; + rface->face = merged_face; + rface->font = font; + + if (font) + { + if (font->type == MFONT_TYPE_SPEC) + rfont = (MRealizedFont *) mfont_find (frame, font, NULL, 0); + else if (font->type == MFONT_TYPE_OBJECT) + { + MFONT_INIT (&spec); + spec.size = (int) merged_face.property[MFONT_SIZE]; + if (font->property[MFONT_REGISTRY]) + spec.property[MFONT_REGISTRY] = font->property[MFONT_REGISTRY]; + else + mfont_put_prop (&spec, Mregistry, + (font->source == MFONT_SOURCE_X + ? Miso8859_1 : Municode_bmp)); + rfont = mfont__open (frame, font, &spec); + } + else + rfont = (MRealizedFont *) font; + } + else + { + MFontset *fontset = (MFontset *) merged_face.property[MFACE_FONTSET]; + + rface->rfontset = mfont__realize_fontset (frame, fontset, &merged_face, + font); + rfont = NULL; + mfont__set_spec_from_face (&spec, &merged_face); + mfont_put_prop (&spec, Mregistry, Municode_bmp); + spec.source = MFONT_SOURCE_FT; + font = mfont__select (frame, &spec, 0); + if (font) + rfont = mfont__open (frame, font, &spec); + if (! rfont) + { + mfont_put_prop (&spec, Mregistry, Miso8859_1); + spec.source = MFONT_SOURCE_X; + font = mfont__select (frame, &spec, 0); + if (font) + rfont = mfont__open (frame, font, &spec); + } + if (! rfont) + { + num = 0; + rfont = mfont__lookup_fontset (rface->rfontset, NULL, &num, + Mlatin, Mnil, Mnil, size, 0); + } + } + + if (rfont) + { + rface->rfont = rfont; + rface->layouter = rfont->layouter; + rfont->layouter = Mnil; + work_gstring.glyphs[0].rface = rface; + work_gstring.glyphs[0].g.code = MCHAR_INVALID_CODE; + work_gstring.glyphs[0].g.measured = 0; + mfont__get_metric (&work_gstring, 0, 1); + rface->ascent = work_gstring.glyphs[0].g.ascent; + rface->descent = work_gstring.glyphs[0].g.descent; + work_gstring.glyphs[0].g.code + = mfont__encode_char (frame, (MFont *) rfont, NULL, ' '); + if (work_gstring.glyphs[0].g.code != MCHAR_INVALID_CODE) + { + work_gstring.glyphs[0].g.measured = 0; + mfont__get_metric (&work_gstring, 0, 1); + rface->space_width = work_gstring.glyphs[0].g.xadv; + } + else + rface->space_width = rfont->spec.size / 10; + if (rfont->average_width) + rface->average_width = rfont->average_width >> 6; + else + { + work_gstring.glyphs[0].g.code + = mfont__encode_char (frame, (MFont *) rfont, NULL, 'x'); + if (work_gstring.glyphs[0].g.code != MCHAR_INVALID_CODE) + { + work_gstring.glyphs[0].g.measured = 0; + mfont__get_metric (&work_gstring, 0, 1); + rface->average_width = work_gstring.glyphs[0].g.xadv; + } + else + rface->average_width = rface->space_width; + } + } + else + { + rface->rfont = NULL; + rface->space_width = frame->space_width; + } + + rface->hline = (MFaceHLineProp *) merged_face.property[MFACE_HLINE]; + if (rface->hline && rface->hline->width == 0) + rface->hline = NULL; + rface->box = (MFaceBoxProp *) merged_face.property[MFACE_BOX]; + if (rface->box && rface->box->width == 0) + rface->box = NULL; + rface->ascii_rface = rface; + (*frame->driver->realize_face) (rface); + + func = rface->face.hook; + if (func && func != noop_hook) + (func) (&(rface->face), rface->info, rface->face.property[MFACE_HOOK_ARG]); + + rface->non_ascii_list = mplist (); + if (rface->rfont) + { + MRealizedFace *nofont; + + MSTRUCT_CALLOC (nofont, MERROR_FACE); + *nofont = *rface; + nofont->non_ascii_list = NULL; + nofont->rfont = NULL; + mplist_add (rface->non_ascii_list, Mt, nofont); + } + + return rface; +} + + +MGlyph * +mface__for_chars (MSymbol script, MSymbol language, MSymbol charset, + MGlyph *from_g, MGlyph *to_g, int size) +{ + MRealizedFont *rfont = from_g->rface->rfont; + MSymbol layouter; + int num = to_g - from_g; + int i; + + if (from_g->rface->font) + { + MRealizedFace *rface = from_g->rface, *new; + + if (! rfont) + rfont = mfontset__get_font (rface->frame, + rface->face.property[MFACE_FONTSET], + script, language, + rface->font, NULL); + else if (script != Mlatin) + rfont = mfontset__get_font (rface->frame, + rface->face.property[MFACE_FONTSET], + script, language, + (MFont *) rfont, NULL); + if (! rfont) + { + for (; from_g < to_g && from_g->rface->font; from_g++) + from_g->g.code = MCHAR_INVALID_CODE; + } + else + { + if (rface->rfont == rfont && rfont->layouter == Mnil) + new = rface; + else + { + MSTRUCT_MALLOC (new, MERROR_FACE); + mplist_push (rface->non_ascii_list, Mt, new); + *new = *rface; + new->rfont = rfont; + new->layouter = rfont->layouter; + rfont->layouter = Mnil; + new->non_ascii_list = NULL; + new->ascent = rfont->ascent >> 6; + new->descent = rfont->descent >> 6; + } + for (; from_g < to_g && from_g->rface->font; from_g++) + { + from_g->rface = new; + if (new->layouter) + { + MFLT *flt = mflt_get (new->layouter); + MCharTable *coverage; + + if (! flt + || ((coverage = mflt_coverage (flt)) + && ! (from_g->g.code + = (unsigned) mchartable_lookup (coverage, + from_g->g.c)))) + { + from_g->rface = rface; + from_g->g.code = mfont__encode_char (rfont->frame, + (MFont *) rfont, + NULL, from_g->g.c); + } + } + else + from_g->g.code = mfont__encode_char (rfont->frame, + (MFont *) rfont, + NULL, from_g->g.c); + } + } + return from_g; + } + + if (rfont && script == Mlatin) + { + for (i = 0; i < num; i++) + { + unsigned code = mfont__encode_char (rfont->frame, (MFont *) rfont, + NULL, from_g[i].g.c); + if (code == MCHAR_INVALID_CODE) + break; + from_g[i].g.code = code; + } + if (i == num || from_g[i].rface->font) + return from_g + i; + } + + rfont = mfont__lookup_fontset (from_g->rface->rfontset, from_g, &num, + script, language, charset, size, 0); + if (rfont) + { + layouter = rfont->layouter; + rfont->layouter = Mnil; + } + else + { + from_g->g.code = MCHAR_INVALID_CODE; + num = 1; + rfont = NULL; + layouter = Mnil; + } + + to_g = from_g + num; + while (from_g < to_g) + { + MGlyph *g = from_g; + MRealizedFace *rface = from_g++->rface; + + while (from_g < to_g && rface == from_g->rface) from_g++; + if (rface->rfont != rfont + || rface->layouter != layouter) + { + MPlist *plist = mplist_find_by_value (rface->non_ascii_list, rfont); + MRealizedFace *new = NULL; + + while (plist) + { + new = MPLIST_VAL (plist); + if (new->layouter == layouter) + break; + plist = mplist_find_by_value (MPLIST_NEXT (plist), rfont); + } + if (! plist) + { + MSTRUCT_MALLOC (new, MERROR_FACE); + mplist_push (rface->non_ascii_list, Mt, new); + *new = *rface; + new->rfont = rfont; + new->layouter = layouter; + new->non_ascii_list = NULL; + if (rfont) + { + new->ascent = rfont->ascent >> 6; + new->descent = rfont->descent >> 6; + } + } + while (g < from_g) + g++->rface = new; + } + } + return to_g; +} + + +void +mface__free_realized (MRealizedFace *rface) +{ + MPlist *plist; + + MPLIST_DO (plist, rface->non_ascii_list) + free (MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (rface->non_ascii_list); + if (rface->font && rface->font->type != MFONT_TYPE_REALIZED) + free (rface->font); + free (rface); +} + +void +mface__update_frame_face (MFrame *frame) +{ + frame->rface = NULL; + frame->rface = mface__realize (frame, NULL, 0, 0, NULL); + frame->space_width = frame->rface->space_width; + frame->average_width = frame->rface->average_width; + frame->ascent = frame->rface->ascent; + frame->descent = frame->rface->descent; +} + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/* External API */ +/*** @addtogroup m17nFace */ +/*** @{ */ +/*=*/ + +/***en @name Variables: Keys of face property */ +/***ja @name �ѿ�: �ե������ץ��ѥƥ��Υ��� */ +/*** @{ */ +/*=*/ + +/***en + @brief Key of a face property specifying foreground color. + + The variable #Mforeground is used as a key of face property. The + property value must be a symbol whose name is a color name, or + #Mnil. + + #Mnil means that the face does not specify a foreground color. + Otherwise, the foreground of an M-text is drawn by the specified + color. */ +/***ja + @brief ���ʿ�����ꤹ��ե������ץ��ѥƥ����Υ���. + + �ѿ� #Mforeground �ϥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣 + �ץ��ѥƥ����ͤϡ���̾��̾���Ȥ��ƻ��ĥ���ܥ뤫 #Mnil �Ǥ��롣 + + #Mnil �ξ�硢���ʿ��ϻ��ꤵ��ʤ��������Ǥʤ���� M-text + �����ʤϻ��ꤵ�줿����ɽ������롣 */ + +MSymbol Mforeground; + +/***en + @brief Key of a face property specifying background color. + + The variable #Mbackground is used as a key of face property. The + property value must be a symbol whose name is a color name, or + #Mnil. + + #Mnil means that the face does not specify a background color. + Otherwise, the background of an M-text is drawn by the specified + color. */ +/***ja + @brief �طʿ�����ꤹ�뤿��Υե������ץ��ѥƥ����Υ���. + + �ѿ� #Mbackground �ϥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣 + �ץ��ѥƥ����ͤϡ���̾��̾���Ȥ��ƻ��ĥ���ܥ뤫 #Mnil �Ǥ��롣 + + #Mnil �ξ�硢�طʿ��ϻ��ꤵ��ʤ��������Ǥʤ���� M-text + ���طʤϻ��ꤵ�줿����ɽ������롣 */ + +MSymbol Mbackground; + +/***en + @brief Key of a face property specifying video mode. + + The variable #Mvideomode is used as a key of face property. The + property value must be @b Mnormal, @b Mreverse, or #Mnil. + + @b Mnormal means that an M-text is drawn in normal video mode + (i.e. the foreground is drawn by foreground color, the background + is drawn by background color). + + @b Mreverse means that an M-text is drawn in reverse video mode + (i.e. the foreground is drawn by background color, the background + is drawn by foreground color). + + #Mnil means that the face does not specify a video mode. */ +/***ja + @brief �ӥǥ��⡼�ɤ���ꤹ�뤿��Υե������ץ��ѥƥ����Υ���. + + �ѿ� #Mvideomode �ϥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣�ץ��ѥƥ����ͤϡ� + @b Mnormal, @b Mreverse, #Mnil �Τ����줫�Ǥʤ��ƤϤʤ�ʤ��� + + @b Mnormal �ξ��ϡ�M-text + ��ɸ��Υӥǥ��⡼�ɡ����ʤ����ʿ��ǡ��طʤ��طʿ��ǡˤ�ɽ�����롣 + + @b Mreverse �ξ��ϥ�С����ӥǥ��⡼�ɤǡ����ʤ��طʿ��ǡ��طʤ����ʿ��ǡ�ɽ�����롣 + + #Mnil �ξ��ϥӥǥ��⡼�ɤϻ��ꤵ��ʤ��� + */ + +MSymbol Mvideomode; + +/***en + @brief Key of a face property specifying font size ratio. + + The variable #Mratio is used as a key of face property. The value + RATIO must be an integer. + + The value 0 means that the face does not specify a font size + ratio. Otherwise, an M-text is drawn by a font of size (FONTSIZE + * RATIO / 100) where FONTSIZE is a font size specified by the face + property #Msize. */ +/***ja + @brief �ե���ȤΥ���������Ψ����ꤹ�뤿��Υե������ץ��ѥƥ����Υ���. + + �ѿ� #Mratio �ϥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣�� RATIO + �������ͤǤʤ��ƤϤʤ�ʤ��� + + �ͤ�0�ʤ�С��ե���ȥ������ϻ��ꤵ��ʤ��������Ǥʤ���С�M-text + ��(FONTSIZE * RATIO / 100) �Ȥ����������Υե���Ȥ�ɽ������롣 + FONTSIZE �ϥե������ץ��ѥƥ���#Msize �ǻ��ꤵ�줿�������Ǥ��롣 */ + +MSymbol Mratio; + +/***en + @brief Key of a face property specifying horizontal line. + + The variable #Mhline is used as a key of face property. The value + must be a pointer to an object of type #MFaceHLineProp, or @c + NULL. + + The value @c NULL means that the face does not specify this + property. Otherwise, an M-text is drawn with a horizontal line by + a way specified by the object that the value points to. */ +/***ja + @brief ��ʿ������ꤹ�뤿��Υե������ץ��ѥƥ����Υ���. + + �ѿ� #Mhline �ϥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣�ͤ� + #MFaceHLineProp �����֥������ȤؤΥݥ��󥿤� @c NULL �Ǥʤ��ƤϤʤ�ʤ��� + + �ͤ� @c NULL �ʤ�С����Υץ��ѥƥ��ϻ��ꤵ��ʤ��� + �����Ǥʤ�����ͤ��ؤ����֥������Ȥ˻��ꤵ�줿�褦�˿�ʿ�����ղä��� M-text + ��ɽ�����롣*/ + +MSymbol Mhline; + +/***en + @brief Key of a face property specifying box. + + The variable #Mbox is used as a key of face property. The value + must be a pointer to an object of type #MFaceBoxProp, or @c NULL. + + The value @c NULL means that the face does not specify a box. + Otherwise, an M-text is drawn with a surrounding box by a way + specified by the object that the value points to. */ +/***ja + @brief �Ϥ��Ȥ���ꤹ�뤿��Υե������ץ��ѥƥ����Υ���. + + �ѿ� #Mbox �ϥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣�ͤ� + #MFaceBoxProp �����֥������ȤؤΥݥ��󥿤� @c NULL �Ǥʤ��ƤϤʤ�ʤ��� + + �ͤ� @c NULL �ʤ�С����Υե������ϰϤ��Ȥ���ꤷ�Ƥ��ʤ��� + �����Ǥʤ�����ͤ��ؤ����֥������Ȥ˻��ꤵ�줿�褦�˰Ϥ��Ȥ��ղä��� + M-text ��ɽ�����롣*/ + +MSymbol Mbox; + +/***en + @brief Key of a face property specifying fontset. + + The variable #Mfontset is used as a key of face property. The + value must be a pointer to an object of type #Mfontset, or @c + NULL. + + The value @c NULL means that the face does not specify a fontset. + Otherwise, an M-text is drawn with a font selected from what + specified in the fontset. */ +/***ja + @brief �ե���ȥ��åȤ���ꤹ�뤿��Υե������ץ��ѥƥ����Υ���. + + �ѿ� #Mfontset �ϥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣�ͤ� + #Mfontset �����֥������ȤؤΥݥ��󥿤� @c NULL �Ǥʤ��ƤϤʤ�ʤ��� + + �ͤ� @c NULL �ʤ�С��ե���ȥ��åȤϻ��ꤵ��Ƥ��ʤ��� + �����Ǥʤ�����ͤ��ؤ����֥������Ȥ˻��ꤵ�줿�ե���ȥ��åȤ���������ե���Ȥ� + M-text ��ɽ�����롣*/ + +MSymbol Mfontset; + +/***en + @brief Key of a face property specifying hook. + + The variable #Mhook_func is used as a key of face property. The + value must be a function of type #MFaceHookFunc, or @c NULL. + + The value @c NULL means that the face does not specify a hook. + Otherwise, the specified function is called before the face is + realized. */ +/***ja + @brief �եå�����ꤹ�뤿��Υե������ץ��ѥƥ����Υ���. + + �ѿ� #Mhook_func �ϥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣�ͤ� + #MFaceHookFunc ���δؿ��� @c NULL �Ǥʤ��ƤϤʤ�ʤ��� + + �ͤ� @c NULL �ʤ�С��եå��ϻ��ꤵ��Ƥ��ʤ��� + �����Ǥʤ���Хե�������¸��������˻��ꤵ�줿�ؿ����ƤФ�롣 */ +MSymbol Mhook_func; + +/***en + @brief Key of a face property specifying argument of hook. + + The variable #Mhook_arg is used as a key of face property. The + value can be anything that is passed a hook function specified by + the face property #Mhook_func. */ +/***ja + @brief �եå��ΰ�������ꤹ�뤿��Υե������ץ��ѥƥ����Υ���. + + �ѿ� #Mhook_arg �ϥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣 + �ͤϲ��Ǥ�褯���ե������ץ��ѥƥ� #Mhook_func �ǻ��ꤵ���ؿ����Ϥ���롣 */ +MSymbol Mhook_arg; + +/*** @} */ +/*=*/ + +/*** @ingroup m17nFace */ +/***en @name Variables: Possible values of #Mvideomode property of face */ +/***ja @name �ѿ��� �ե������� #Mvideomode �ץ��ѥƥ��β�ǽ���� */ +/*** @{ */ + +/***en + See the documentation of the variable #Mvideomode. */ +/***ja + �ѿ� #Mvideomode �������򻲾ȤΤ��ȡ� */ +MSymbol Mnormal; +MSymbol Mreverse; +/*** @} */ +/*=*/ + +/*** @ingroup m17nFace */ +/***en @name Variables: Predefined faces */ +/***ja @name �ѿ�: ����Ѥߥե����� */ +/*** @{ */ +/*=*/ + +/***en + @brief Normal video face. + + The variable #mface_normal_video points to a face that has the + #Mvideomode property with value @b Mnormal. The other properties + are not specified. An M-text drawn with this face appear normal + colors (i.e. the foreground is drawn by foreground color, and + background is drawn by background color). */ +/***ja + @brief ɸ��ӥǥ��ե�����. + + �ѿ� #mface_normal_video �� #Mvideomode �ץ��ѥƥ����ͤ� @b Mnormal + �Ǥ���ե�������ؤ��ݥ��󥿤Ǥ��롣¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ��� + ���Υե�������ɽ�������M-text + ��ɸ��ο� (���ʤ�����ʤ����ʿ����طʤ��طʿ��ˤ�������롣 */ + +MFace *mface_normal_video; + +/***en + @brief Reverse video face. + + The variable #mface_reverse_video points to a face that has the + #Mvideomode property with value @b Mreverse. The other properties + are not specified. An M-text drawn with this face appear in + reversed colors (i.e. the foreground is drawn by background + color, and background is drawn by foreground color). */ +/***ja + @brief ��С����ӥǥ��ե�����. + + �ѿ� #mface_reverse_video �� #Mvideomode �ץ��ѥƥ����ͤ� + @b Mreverse �Ǥ���ե�������ؤ��ݥ��󥿤Ǥ��롣¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ��� + ���Υե�������ɽ�������M-text + �����ʿ����طʿ��������ؤ�ä� (���ʤ�����ʤ��طʿ����طʤ����ʿ���������롣 */ + +MFace *mface_reverse_video; + +/***en + @brief Underline face. + + The variable #mface_underline points to a face that has the + #Mhline property with value a pointer to an object of type + #MFaceHLineProp. The members of the object are as follows: + +@verbatim + member value + ----- ----- + type MFACE_HLINE_UNDER + width 1 + color Mnil +@endverbatim + + The other properties are not specified. An M-text that has this + face is drawn with an underline. */ +/***ja + @brief �����ե�����. + + �ѿ� #mface_underline �� #Mhline �ץ��ѥƥ����ͤ� #MFaceHLineProp + �����֥������ȤؤΥݥ��󥿤Ǥ���ե�������ؤ��ݥ��󥿤Ǥ��롣���֥������ȤΥ��Фϰʲ����̤ꡣ + +@verbatim + ���� �� + ----- ----- + type MFACE_HLINE_UNDER + width 1 + color Mnil +@endverbatim + + ¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ������Υե���������� M-text �ϲ����դ���ɽ������롣*/ + +MFace *mface_underline; + +/***en + @brief Medium face. + + The variable #mface_medium points to a face that has the #Mweight + property with value a symbol of name "medium". The other + properties are not specified. An M-text that has this face is + drawn with a font of medium weight. */ +/***ja + @brief �ߥǥ�����ե�����. + + �ѿ� #mface_medium �� #Mweight �ץ��ѥƥ����ͤ� "medium" + �Ȥ���̾�����ĥ���ܥ�Ǥ���褦�ʥե�������ؤ��ݥ��󥿤Ǥ��롣 + ¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ������Υե���������� M-text + �ϡ��ߥǥ����०�����ȤΥե���Ȥ�ɽ������롣 */ +MFace *mface_medium; + +/***en + @brief Bold face. + + The variable #mface_bold points to a face that has the #Mweight + property with value a symbol of name "bold". The other properties + are not specified. An M-text that has this face is drawn with a + font of bold weight. */ +/***ja + @brief �ܡ���ɥե�����. + + �ѿ� #mface_bold �� #Mweight �ץ��ѥƥ����ͤ� "bold" + �Ȥ���̾�����ĥ���ܥ�Ǥ���褦�ʥե�������ؤ��ݥ��󥿤Ǥ��롣 + ¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ������Υե���������� M-text + �ϡ��ܡ���ɥե���Ȥ�ɽ������롣 */ + +MFace *mface_bold; + +/***en + @brief Italic face. + + The variable #mface_italic points to a face that has the #Mstyle + property with value a symbol of name "italic". The other + properties are not specified. An M-text that has this face is + drawn with a font of italic style. */ +/***ja + @brief ������å��ե�����. + + �ѿ� #mface_italic �� #Mstyle �ץ��ѥƥ����ͤ� "italic" + �Ȥ���̾�����ĥ���ܥ�Ǥ���褦�ʥե�������ؤ��ݥ��󥿤Ǥ��롣 + ¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ������Υե���������� M-text + �ϡ�������å��Τ�ɽ������롣 */ + +MFace *mface_italic; + +/***en + @brief Bold italic face. + + The variable #mface_bold_italic points to a face that has the + #Mweight property with value a symbol of name "bold", and #Mstyle + property with value a symbol of name "italic". The other + properties are not specified. An M-text that has this face is + drawn with a font of bold weight and italic style. */ +/***ja + @brief �ܡ���ɥ�����å��ե�����. + + �ѿ� #mface_bold_italic �ϡ�#Mweight �ץ��ѥƥ����ͤ� "bold" + �Ȥ���̾�����ĥ���ܥ�Ǥ��ꡢ���� #Mstyle �ץ��ѥƥ����ͤ� "italic" + �Ȥ���̾�����ĥ���ܥ�Ǥ���褦�ʥե�������ؤ��ݥ��󥿤Ǥ��롣 + ¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ������Υե���������� M-text + �ϡ��ܡ���ɥ�����å��Τ�ɽ������롣 */ + +MFace *mface_bold_italic; + +/***en + @brief Smallest face. + + The variable #mface_xx_small points to a face that has the #Mratio + property with value 50. The other properties are not specified. + An M-text that has this face is drawn with a font whose size is + 50% of a normal font. */ +/***ja + @brief �Ǿ��Υե�����. + + �ѿ� #mface_xx_small �ϡ�#Mratio �ץ��ѥƥ����ͤ� 50 + �Ǥ���ե�������ؤ��ݥ��󥿤Ǥ��롣¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ��� + ���Υե���������� M-text ��ɸ��ե���Ȥ� 50% ���礭���Υե���Ȥ��Ѥ���ɽ������롣 + */ + +MFace *mface_xx_small; + +/***en + @brief Smaller face. + + The variable #mface_x_small points to a face that has the #Mratio + property with value 66. The other properties are not specified. + An M-text that has this face is drawn with a font whose size is + 66% of a normal font. */ +/***ja + @brief ��꾮�����ե�����. + + �ѿ� #mface_x_small �ϡ�#Mratio �ץ��ѥƥ����ͤ� 66 + �Ǥ���ե�������ؤ��ݥ��󥿤Ǥ��롣¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ��� + ���Υե���������� M-text ��ɸ��ե���Ȥ� 66% ���礭���Υե���Ȥ��Ѥ���ɽ������롣 + */ + +MFace *mface_x_small; + +/***en + @brief Small face. + + The variable #mface_x_small points to a face that has the #Mratio + property with value 75. The other properties are not specified. + An M-text that has this face is drawn with a font whose size is + 75% of a normal font. */ +/***ja + @brief �������ե�����. + + �ѿ� #mface_small �ϡ�#Mratio �ץ��ѥƥ����ͤ� 75 + �Ǥ���ե�������ؤ��ݥ��󥿤Ǥ��롣¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ��� + ���Υե���������� M-text ��ɸ��ե���Ȥ� 75% ���礭���Υե���Ȥ��Ѥ���ɽ������롣 + */ + +MFace *mface_small; + +/***en + @brief Normalsize face. + + The variable #mface_normalsize points to a face that has the + #Mratio property with value 100. The other properties are not + specified. An M-text that has this face is drawn with a font + whose size is the same as a normal font. */ +/***ja + @brief ɸ����礭���Υե�����. + + �ѿ� #mface_normalsize �ϡ�#Mratio �ץ��ѥƥ����ͤ� 100 + �Ǥ���ե�������ؤ��ݥ��󥿤Ǥ��롣¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ��� + ���Υե���������� M-text ��ɸ��ե���Ȥ�Ʊ���礭���Υե���Ȥ��Ѥ���ɽ������롣 + */ + +MFace *mface_normalsize; + +/***en + @brief Large face. + + The variable #mface_large points to a face that has the #Mratio + property with value 120. The other properties are not specified. + An M-text that has this face is drawn with a font whose size is + 120% of a normal font. */ +/***ja + @brief �礭���ե�����. + + �ѿ� #mface_large �ϡ�#Mratio �ץ��ѥƥ����ͤ� 120 + �Ǥ���ե�������ؤ��ݥ��󥿤Ǥ��롣¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ��� + ���Υե���������� M-text ��ɸ��ե���Ȥ� 120% ���礭���Υե���Ȥ��Ѥ���ɽ������롣 + */ + +MFace *mface_large; + +/***en + @brief Larger face. + + The variable #mface_x_large points to a face that has the #Mratio + property with value 150. The other properties are not specified. + An M-text that has this face is drawn with a font whose size is + 150% of a normal font. */ +/***ja + @brief ��ä��礭���ե�����. + + �ѿ� #mface_x_large �ϡ�#Mratio �ץ��ѥƥ����ͤ� 150 + �Ǥ���ե�������ؤ��ݥ��󥿤Ǥ��롣¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ��� + ���Υե���������� M-text ��ɸ��ե���Ȥ� 150% ���礭���Υե���Ȥ��Ѥ���ɽ������롣 + */ + +MFace *mface_x_large; + +/***en + @brief Largest face. + + The variable #mface_xx_large points to a face that has the #Mratio + property with value 200. The other properties are not specified. + An M-text that has this face is drawn with a font whose size is + 200% of a normal font. */ +/***ja + @brief ����Υե�����. + + �ѿ� #mface_xx_large �ϡ�#Mratio �ץ��ѥƥ����ͤ� 200 + �Ǥ���ե�������ؤ��ݥ��󥿤Ǥ��롣¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ��� + ���Υե���������� M-text ��ɸ��ե���Ȥ� 200% ���礭���Υե���Ȥ��Ѥ���ɽ������롣 + */ + +MFace *mface_xx_large; + +/***en + @brief Black face. + + The variable #mface_black points to a face that has the + #Mforeground property with value a symbol of name "black". The + other properties are not specified. An M-text that has this face + is drawn with black foreground. */ +/***ja + @brief ���ե�����. + + �ѿ� #mface_black �ϡ�#Mforeground �ץ��ѥƥ����ͤȤ��� "black" + �Ȥ���̾���Υ���ܥ����Ĥ褦�ʥե�������ؤ��ݥ��󥿤Ǥ��롣 + ¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ������Υե���������� M-text + �����ʿ��Ȥ��ƹ����Ѥ���ɽ������롣 */ + +MFace *mface_black; + +/***en + @brief White face. + + The variable #mface_white points to a face that has the + #Mforeground property with value a symbol of name "white". The + other properties are not specified. An M-text that has this face + is drawn with white foreground. */ +/***ja + @brief ��ե�����. + + �ѿ� #mface_white �ϡ�#Mforeground �ץ��ѥƥ����ͤȤ��� "white" + �Ȥ���̾���Υ���ܥ����Ĥ褦�ʥե�������ؤ��ݥ��󥿤Ǥ��롣 + ¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ������Υե���������� M-text + �����ʿ��Ȥ�������Ѥ���ɽ������롣 */ + +MFace *mface_white; + +/***en + @brief Red face. + + The variable #mface_red points to a face that has the + #Mforeground property with value a symbol of name "red". The + other properties are not specified. An M-text that has this face + is drawn with red foreground. */ +/***ja + @brief �֥ե�����. + + �ѿ� #mface_red �ϡ�#Mforeground �ץ��ѥƥ����ͤȤ��� "red" + �Ȥ���̾���Υ���ܥ����Ĥ褦�ʥե�������ؤ��ݥ��󥿤Ǥ��롣 + ¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ������Υե���������� M-text + �����ʿ��Ȥ����֤��Ѥ���ɽ������롣 */ + +MFace *mface_red; + +/***en + @brief Green face. + + The variable #mface_green points to a face that has the + #Mforeground property with value a symbol of name "green". The + other properties are not specified. An M-text that has this face + is drawn with green foreground. */ +/***ja + @brief �Хե�����. + + �ѿ� #mface_green �ϡ�#Mforeground �ץ��ѥƥ����ͤȤ��� "green" + �Ȥ���̾���Υ���ܥ����Ĥ褦�ʥե�������ؤ��ݥ��󥿤Ǥ��롣 + ¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ������Υե���������� M-text + �����ʿ��Ȥ����Ф��Ѥ���ɽ������롣 */ + +MFace *mface_green; + +/***en + @brief Blue face. + + The variable #mface_blue points to a face that has the + #Mforeground property with value a symbol of name "blue". The + other properties are not specified. An M-text that has this face + is drawn with blue foreground. */ +/***ja + @brief �ĥե�����. + + �ѿ� #mface_blue �ϡ�#Mforeground �ץ��ѥƥ����ͤȤ��� "blue" + �Ȥ���̾���Υ���ܥ����Ĥ褦�ʥե�������ؤ��ݥ��󥿤Ǥ��롣 + ¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ������Υե���������� M-text + �����ʿ��Ȥ����Ĥ��Ѥ���ɽ������롣 */ + +MFace *mface_blue; + +/***en + @brief Cyan face. + + The variable #mface_cyan points to a face that has the + #Mforeground property with value a symbol of name "cyan". The + other properties are not specified. An M-text that has this face + is drawn with cyan foreground. */ +/***ja + @brief ������ե�����. + + �ѿ� #mface_cyan �ϡ�#Mforeground �ץ��ѥƥ����ͤȤ��� "cyan" + �Ȥ���̾���Υ���ܥ����Ĥ褦�ʥե�������ؤ��ݥ��󥿤Ǥ��롣 + ¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ������Υե���������� M-text + �����ʿ��Ȥ��ƥ�������Ѥ���ɽ������롣 */ + +MFace *mface_cyan; + +/***en + @brief yellow face. + + The variable #mface_yellow points to a face that has the + #Mforeground property with value a symbol of name "yellow". The + other properties are not specified. An M-text that has this face + is drawn with yellow foreground. */ + +/***ja + @brief ���ե�����. + + �ѿ� #mface_yellow �ϡ�#Mforeground �ץ��ѥƥ����ͤȤ��� "yellow" + �Ȥ���̾���Υ���ܥ����Ĥ褦�ʥե�������ؤ��ݥ��󥿤Ǥ��롣 + ¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ������Υե���������� M-text + �����ʿ��Ȥ��Ʋ������Ѥ���ɽ������롣 */ + +MFace *mface_yellow; + +/***en + @brief Magenta face. + + The variable #mface_magenta points to a face that has the + #Mforeground property with value a symbol of name "magenta". The + other properties are not specified. An M-text that has this face + is drawn with magenta foreground. */ + +/***ja + @brief �ޥ��󥿥ե�����. + + �ѿ� #mface_magenta �ϡ�#Mforeground �ץ��ѥƥ����ͤȤ��� + "magenta" �Ȥ���̾���Υ���ܥ����Ĥ褦�ʥե�������ؤ��ݥ��󥿤Ǥ��롣 + ¾�Υץ��ѥƥ��ϻ��ꤵ��ʤ������Υե���������� M-text + �����ʿ��Ȥ��ƥޥ��󥿤��Ѥ���ɽ������롣 */ + +MFace *mface_magenta; + +/*** @} */ +/*=*/ + +/***en @name Variables: The other symbols for face handling. */ +/***ja @name �ѿ�: �ե��������갷������Τ���¾�Υ���ܥ� */ +/*** @{ */ +/*=*/ + +/***en + @brief Key of a text property specifying a face. + + The variable #Mface is a symbol of name "face". A text + property whose key is this symbol must have a pointer to an object + of type #MFace. This is a managing key. */ + +/***ja + @brief �ե���������ꤹ��ƥ����ȥץ��ѥƥ��Υ���. + + �ѿ� #Mface �� "face" + �Ȥ���̾������ĥ���ܥ�Ǥ��롣���Υ���ܥ�򥭡��Ȥ���ƥ����ȥץ��ѥƥ��ϡ� + #MFace ���Υ��֥������ȤؤΥݥ��󥿤�����ʤ���Фʤ�ʤ��� + ����ϴ��������Ǥ��롣 */ + +MSymbol Mface; +/*=*/ +/*** @} */ +/*=*/ + +/***en + @brief Create a new face. + + The mface () function creates a new face object that specifies no + property. + + @return + This function returns a pointer to the created face. */ + +/***ja + @brief �������ե�������Ĥ���. + + �ؿ� mface () + �ϥץ��ѥƥ�����ڻ����ʤ��������ե��������֥������Ȥ��롣 + + @return + ���δؿ��Ϻ�ä��ե������ؤΥݥ��󥿤��֤��� */ + +MFace * +mface () +{ + MFace *face; + + M17N_OBJECT (face, free_face, MERROR_FACE); + face->frame_list = mplist (); + M17N_OBJECT_REGISTER (face_table, face); + return face; +} + +/*=*/ + +/***en + @brief Make a copy of a face. + + The mface_copy () function makes a copy of $FACE and returns a + pointer to the created copy. */ + +/***ja + @brief �ե������Υ��ԡ�����. + + �ؿ� mface_copy () �ϥե����� $FACE + �Υ��ԡ����ꡢ���Υ��ԡ��ؤΥݥ��󥿤��֤��� */ + +MFace * +mface_copy (MFace *face) +{ + MFace *copy; + + MSTRUCT_CALLOC (copy, MERROR_FACE); + *copy = *face; + copy->control.ref_count = 1; + M17N_OBJECT_REGISTER (face_table, copy); + copy->frame_list = mplist (); + if (copy->property[MFACE_FONTSET]) + M17N_OBJECT_REF (copy->property[MFACE_FONTSET]); + return copy; +} + +/*=*/ +/***en + @brief Compare faces. + + The mface_equal () function compares faces $FACE1 and $FACE2. + + @return + If two faces have the same property values, return 1. + Otherwise return 0. */ + +int +mface_equal (MFace *face1, MFace *face2) +{ + MFaceHLineProp *hline1, *hline2; + MFaceBoxProp *box1, *box2; + int i; + + if (face1 == face2) + return 1; + if (memcmp (face1->property, face2->property, sizeof face1->property) == 0) + return 1; + for (i = MFACE_FOUNDRY; i <= MFACE_BACKGROUND; i++) + if (face1->property[i] != face2->property[i]) + return 0; + for (i = MFACE_VIDEOMODE; i <= MFACE_RATIO; i++) + if (face1->property[i] != face2->property[i]) + return 0; + hline1 = (MFaceHLineProp *) face1->property[MFACE_HLINE]; + hline2 = (MFaceHLineProp *) face2->property[MFACE_HLINE]; + if (hline1 != hline2) + { + if (! hline1 || ! hline2) + return 0; + if (memcmp (hline1, hline2, sizeof (MFaceHLineProp)) != 0) + return 0; + } + box1 = (MFaceBoxProp *) face1->property[MFACE_BOX]; + box2 = (MFaceBoxProp *) face2->property[MFACE_BOX]; + if (box1 != box2) + { + if (! box1 || ! box2) + return 0; + if (memcmp (box1, box2, sizeof (MFaceBoxProp)) != 0) + return 0; + } + return 1; +} + + +/*=*/ +/***en + @brief Merge faces. + + The mface_merge () functions merges the properties of face $SRC + into $DST. + + @return + This function returns $DST. */ + +/***ja + @brief �ե����������礹��. + + �ؿ� mface_merge () �ϡ��ե����� $SRC �Υץ��ѥƥ���ե����� $DST + �����礹�롣 + + @return + ���δؿ��� $DST ���֤��� */ + +MFace * +mface_merge (MFace *dst, MFace *src) +{ + int i; + MPlist *plist; + + for (i = 0; i < MFACE_PROPERTY_MAX; i++) + if (src->property[i]) + { + if (i == MFACE_FONTSET) + { + M17N_OBJECT_UNREF (dst->property[i]); + M17N_OBJECT_REF (src->property[i]); + } + dst->property[i] = src->property[i]; + } + + MPLIST_DO (plist, dst->frame_list) + { + MFrame *frame = MPLIST_VAL (plist); + + frame->tick++; + if (dst == frame->face) + mface__update_frame_face (frame); + } + + return dst; +} + +/*=*/ + +/***en + @brief Make a face from a font. + + The mface_from_font () function return a newly created face while + reflecting the properties of $FONT in its properties. */ + +/***ja + @brief �ե���Ȥ���ե���������. + + �ؿ� mface_from_font () �ϥե���� $FONT + �Υץ��ѥƥ���ץ��ѥƥ��Ȥ��ƻ��Ŀ������ե��������ꡢ������֤��� */ + +MFace * +mface_from_font (MFont *font) +{ + MFace *face = mface (); + + face->property[MFACE_FOUNDRY] = mfont_get_prop (font, Mfoundry); + face->property[MFACE_FAMILY] = mfont_get_prop (font, Mfamily); + face->property[MFACE_WEIGHT] = mfont_get_prop (font, Mweight); + face->property[MFACE_STYLE] = mfont_get_prop (font, Mstyle); + face->property[MFACE_STRETCH] = mfont_get_prop (font, Mstretch); + face->property[MFACE_ADSTYLE] = mfont_get_prop (font, Madstyle); + face->property[MFACE_SIZE] = mfont_get_prop (font, Msize); + return face; +} + +/*=*/ + +/***en + @brief Get the value of a face property. + + The mface_get_prop () function returns the value of the face + property whose key is $KEY in face $FACE. $KEY must be one of the + followings: + + #Mforeground, #Mbackground, #Mvideomode, #Mhline, #Mbox, + #Mfoundry, #Mfamily, #Mweight, #Mstyle, #Mstretch, #Madstyle, + #Msize, #Mfontset, #Mratio, #Mhook_func, #Mhook_arg + + @return + The actual type of the returned value depends of $KEY. See + documentation of the above keys. If an error is detected, it + returns @c NULL and assigns an error code to the external variable + #merror_code. */ + +/***ja + @brief �ե������Υץ��ѥƥ����ͤ�����. + + �ؿ� mface_get_prop () �ϡ��ե����� $FACE + �����ĥե������ץ��ѥƥ����⡢������ $KEY �Ǥ����Τ��ͤ��֤��� + $KEY �ϲ����Τ����줫�Ǥʤ���Фʤ�ʤ��� + + #Mforeground, #Mbackground, #Mvideomode, #Mhline, #Mbox, + #Mfoundry, #Mfamily, #Mweight, #Mstyle, #Mstretch, #Madstyle, + #Msize, #Mfontset, #Mratio, #Mhook_arg + + @return + ����ͤη��� $KEY �˰�¸���롣�嵭�Υ����������򻲾Ȥ��뤳�ȡ� + ���顼�����Ф��줿���� @c NULL ���֤��������ѿ� #merror_code + �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @seealso + mface_put_prop (), mface_put_hook () + + @errors + @c MERROR_FACE */ + +void * +mface_get_prop (MFace *face, MSymbol key) +{ + int index = (int) msymbol_get (key, M_face_prop_index) - 1; + + if (index < 0) + { + if (key == Mhook_func) + /* This unsafe code is for backward compatiblity. */ + return (void *) face->hook; + MERROR (MERROR_FACE, NULL); + } + return face->property[index]; +} + +/*=*/ + +/***en + @brief Get the hook function of a face. + + The mface_get_hook () function returns the hook function of face + $FACE. */ + +/***ja + @brief �ե������Υեå��ؿ�������. + + �ؿ� mface_get_hook () �ϥե����� $FACE �Υեå��ؿ����֤��� */ + +MFaceHookFunc +mface_get_hook (MFace *face) +{ + return face->hook; +} + +/*=*/ + +/***en + @brief Set a value of a face property. + + The mface_put_prop () function assigns $VAL to the property whose + key is $KEY in face $FACE. $KEY must be one the followings: + + #Mforeground, #Mbackground, #Mvideomode, #Mhline, #Mbox, + #Mfoundry, #Mfamily, #Mweight, #Mstyle, #Mstretch, #Madstyle, + #Msize, #Mfontset, #Mratio, #Mhook_func, #Mhook_arg + + Among them, font related properties (#Mfoundry through #Msize) are + used as the default values when a font in the fontset of $FACE + does not specify those values. + + The actual type of the returned value depends of $KEY. See + documentation of the above keys. + + @return + If the operation was successful, mface_put_prop () returns 0. + Otherwise it returns -1 and assigns an error code to the external + variable #merror_code. */ + +/***ja + @brief �ե������ץ��ѥƥ����ͤ����ꤹ��. + + �ؿ� mface_put_prop () �ϡ��ե����� $FACE ��ǥ����� $KEY + �Ǥ���ץ��ѥƥ����ͤ� $VAL �����ꤹ�롣$KEY + �ϰʲ��Τ����줫�Ǥʤ��ƤϤʤ�ʤ��� + + #Mforeground, #Mbackground, #Mvideomode, #Mhline, #Mbox, + #Mfoundry, #Mfamily, #Mweight, #Mstyle, #Mstretch, #Madstyle, + #Msize, #Mfontset, #Mratio, #Mhook_func, #Mhook_arg. + + �����Τ����Ρ��ե���ȴ�Ϣ�Υץ��ѥƥ� (#Mfamily ���� #Msize + �ޤ�) �ϡ��ե������Υե���ȥ��å���Υե���Ȥ˴ؤ���ǥե�����ͤȤʤꡢ�ġ��Υե���Ȥ��ͤ���ꤷ�ʤ��ä������Ѥ����롣 + + ����ͤη��� $KEY �˰�¸���롣�嵭�Υ����������򻲾Ȥ��뤳�ȡ� + + @return + ����������������硢mface_put_prop () �� 0 ���֤������Ԥ������� + -1 ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @seealso + mface_get_prop () + + @errors + @c MERROR_FACE */ + +int +mface_put_prop (MFace *face, MSymbol key, void *val) +{ + int index = (int) msymbol_get (key, M_face_prop_index) - 1; + MPlist *plist; + + if (key == Mhook_func) + { + /* This unsafe code is for backward compatiblity. */ + if (face->hook == (MFaceHookFunc) val) + return 0; + face->hook = (MFaceHookFunc) val; + } + else + { + if (index < 0) + MERROR (MERROR_FACE, -1); + if (key == Mfontset) + { + if (face->property[index]) + M17N_OBJECT_UNREF (face->property[index]); + M17N_OBJECT_REF (val); + } + else if (key == Mhline) + val = get_hline_create (val); + else if (key == Mbox) + val = get_box_create (val); + + if (face->property[index] == val) + return 0; + face->property[index] = val; + } + + MPLIST_DO (plist, face->frame_list) + { + MFrame *frame = MPLIST_VAL (plist); + + frame->tick++; + if (face == frame->face) + mface__update_frame_face (frame); + } + + return 0; +} + +/*=*/ + +/***en + @brief Set a hook function to a face. + + The mface_set_hook () function sets the hook function of face + $FACE to $FUNC. */ + +/***ja + @brief �ե������Υեå��ؿ������ꤹ��. + + �ؿ� mface_set_hook () �ϡ��ե����� $FACE �Υեå��ؿ���$FUNC ���� + �ꤹ�롣 */ + +int +mface_put_hook (MFace *face, MFaceHookFunc func) +{ + if (face->hook != func) + { + MPlist *plist; + face->hook = func; + + MPLIST_DO (plist, face->frame_list) + { + MFrame *frame = MPLIST_VAL (plist); + + frame->tick++; + if (face == frame->face) + mface__update_frame_face (frame); + } + } + return 0; +} + +/*=*/ + +/***en + @brief Update a face. + + The mface_update () function update face $FACE on frame $FRAME by + calling a hook function of $FACE (if any). */ + +/***ja + @brief �ե������򹹿�����. + + �ؿ� mface_update () �ϥե졼�� $FRAME �Υե����� $FACE �� $FACE + �Υեå��ؿ���ʤ���С˸Ƥ�ǹ������롣 */ + +void +mface_update (MFrame *frame, MFace *face) +{ + MFaceHookFunc func = face->hook; + MPlist *rface_list; + MRealizedFace *rface; + + if (func && func != noop_hook) + { + MPLIST_DO (rface_list, frame->realized_face_list) + { + rface = MPLIST_VAL (rface_list); + if (rface->face.hook == func) + (func) (&(rface->face), rface->face.property[MFACE_HOOK_ARG], + rface->info); + } + } +} +/*=*/ + +/*** @} */ +/*=*/ + +/*** @addtogroup m17nDebug */ +/*** @{ */ +/*=*/ + +/***en + @brief Dump a face. + + The mdebug_dump_face () function prints face $FACE in a human + readable way to the stderr or to what specified by the environment + variable MDEBUG_OUTPUT_FILE. $INDENT specifies how many columns + to indent the lines but the first one. + + @return + This function returns $FACE. */ + +/***ja + @brief �ե����������פ���. + + �ؿ� mdebug_dump_face () �ϥե����� $FACE ��ɸ�२�顼���Ϥ⤷���� + �Ķ��ѿ� MDEBUG_DUMP_FONT �ǻ��ꤵ�줿�ե�����˿ʹ֤˲��ɤʷ��ǰ� + �����롣 $INDENT �ϣ����ܰʹߤΥ���ǥ�Ȥ���ꤹ�롣 + + @return + ���δؿ��� $FACE ���֤��� */ + +MFace * +mdebug_dump_face (MFace *face, int indent) +{ + char *prefix = (char *) alloca (indent + 1); + MFont spec; + + memset (prefix, 32, indent); + prefix[indent] = 0; + mfont__set_spec_from_face (&spec, face); + fprintf (mdebug__output, "(face font:\""); + mdebug_dump_font (&spec); + fprintf (mdebug__output, "\"\n %s fore:%s back:%s", prefix, + msymbol_name ((MSymbol) face->property[MFACE_FOREGROUND]), + msymbol_name ((MSymbol) face->property[MFACE_BACKGROUND])); + if (face->property[MFACE_FONTSET]) + fprintf (mdebug__output, " non-default-fontset"); + fprintf (mdebug__output, " hline:%s", + face->property[MFACE_HLINE] ? "yes" : "no"); + fprintf (mdebug__output, " box:%s)", + face->property[MFACE_BOX] ? "yes" : "no"); + return face; +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/face.h b/src/face.h new file mode 100644 index 0000000..45de4e2 --- /dev/null +++ b/src/face.h @@ -0,0 +1,131 @@ +/* face.h -- header file for the face module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_FACE_H_ +#define _M17N_FACE_H_ + +enum MFaceProperty + { + /** The font related properties. */ + /* The order of MFACE_FOUNDRY to MFACE_ADSTYLE must be the same as + MFONT_FOUNDRY to MFONT_ADSTYLE of enum MFontProperty. */ + MFACE_FOUNDRY, + MFACE_FAMILY, + MFACE_WEIGHT, + MFACE_STYLE, + MFACE_STRETCH, + MFACE_ADSTYLE, + MFACE_SIZE, + MFACE_FONTSET, + + /** The color related properties. */ + MFACE_FOREGROUND, + MFACE_BACKGROUND, + + /** The other properties. */ + MFACE_HLINE, + MFACE_BOX, + MFACE_VIDEOMODE, + + /* In a realized face, this is ignored because it is already + reflected in MFACE_SIZE. */ + MFACE_RATIO, + + MFACE_HOOK_ARG, + + MFACE_PROPERTY_MAX + }; + +struct MFace +{ + M17NObject control; + + /** Properties of the face. */ + void *property[MFACE_PROPERTY_MAX]; + + MFaceHookFunc hook; + + /** List of frames affected by the face modification. */ + MPlist *frame_list; +}; + + +/** A realized face is registered in MFrame->face_list, thus it does + not have to be a managed object. */ + +struct MRealizedFace +{ + /** Frame on which this realized face is created. */ + MFrame *frame; + + /** Properties of all stacked faces are merged into here. */ + MFace face; + + /** Font explicitly specified for the face (maybe NULL). */ + MFont *font; + + /** From what faces this is realized. Keys are Mface and values are + (MFace *). */ + MPlist *base_face_list; + + /* Realized font, one of ->realized_font_list. */ + MRealizedFont *rfont; + + /* Realized fontset, one of ->realized_fontset_list. */ + MRealizedFontset *rfontset; + + MSymbol layouter; + + MFaceHLineProp *hline; + + MFaceBoxProp *box; + + /** Realized face for ASCII chars that has the same face + properties. */ + MRealizedFace *ascii_rface; + + /** List of realized faces that have the same face properties. */ + MPlist *non_ascii_list; + + int ascent, descent; + int space_width; + int average_width; + + /** Pointer to a window system dependent object. */ + void *info; +}; + + +extern MFace *mface__default; + +extern MRealizedFace *mface__realize (MFrame *frame, MFace **faces, int num, + int limitted_size, MFont *font); + +extern MGlyph *mface__for_chars (MSymbol script, MSymbol language, + MSymbol charset, MGlyph *from_g, MGlyph *to_g, + int size); + +extern void mface__free_realized (MRealizedFace *rface); + +extern void mface__update_frame_face (MFrame *frame); + +#endif /* _M17N_FACE_H_ */ diff --git a/src/font-ft.c b/src/font-ft.c new file mode 100644 index 0000000..d617f03 --- /dev/null +++ b/src/font-ft.c @@ -0,0 +1,2970 @@ +/* font-ft.c -- FreeType interface sub-module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "m17n-gui.h" +#include "m17n-misc.h" +#include "internal.h" +#include "plist.h" +#include "symbol.h" +#include "language.h" +#include "internal-flt.h" +#include "internal-gui.h" +#include "font.h" +#include "face.h" + +#ifdef HAVE_FREETYPE + +#ifdef HAVE_FTBDF_H +#include FT_BDF_H +#endif + +static int mdebug_flag = MDEBUG_FONT; + +#ifdef HAVE_FONTCONFIG +#include + +static FcConfig *fc_config; +static MSymbol Mgeneric_family; +#endif /* HAVE_FONTCONFIG */ + +/* Font properties; Mnormal is already defined in face.c. */ +static MSymbol Mmedium, Mr, Mnull; + +static MSymbol M0[5], M3_1, M1_0; + +static FT_Library ft_library; + +#ifdef HAVE_OTF +static OTF *invalid_otf = (OTF *) ""; +static OTF *get_otf (MFLTFont *font, FT_Face *ft_face); +#endif /* HAVE_OTF */ + +typedef struct +{ + MFont font; +#ifdef HAVE_OTF + /* NULL if not yet opened. invalid_otf if not OTF. */ + OTF *otf; +#endif /* HAVE_OTF */ +#ifdef HAVE_FONTCONFIG + FcLangSet *langset; + FcCharSet *charset; +#endif /* HAVE_FONTCONFIG */ +} MFontFT; + +typedef struct +{ + M17NObject control; + FT_Face ft_face; /* This must be the 2nd member. */ + MPlist *charmap_list; + int face_encapsulated; +} MRealizedFontFT; + +typedef struct +{ + char *ft_style; + int len; + enum MFontProperty prop; + char *val; +} MFTtoProp; + +static MFTtoProp ft_to_prop[] = + { { "italic", 0, MFONT_STYLE, "i" }, + { "roman", 0, MFONT_STYLE, "r" }, + { "oblique", 0, MFONT_STYLE, "o" }, + { "regular", 0, MFONT_WEIGHT, "normal" }, + { "normal", 0, MFONT_WEIGHT, "normal" }, + /* We need this entry even if "bold" is in commone_weight[] to + handle such style names as "bolditalic" and "boldoblique". */ + { "bold", 0, MFONT_WEIGHT, "bold" }, + { "demi bold", 0, MFONT_WEIGHT, "demibold" }, + { "demi", 0, MFONT_WEIGHT, "demibold" } }; +static int ft_to_prop_size = sizeof ft_to_prop / sizeof ft_to_prop[0]; + +/** List of FreeType fonts. Keys are family names, values are plists + containing fonts of the corresponding family. In the deeper + plist, keys are file names, values are (MFontFT *). */ +static MPlist *ft_font_list; + +/** List of FreeType fonts. Keys are script names, values are plists + containing fonts supporting the corresponding script. In the + deeper plist, keys are family names, values are (MFontFT *). */ +static MPlist *ft_script_list; + +/** List of FreeType fonts. Keys are language names, values are + plists containing fonts supporting the corresponding language. In + the deeper plist, keys are family names, values are (MFontFT *). */ +static MPlist *ft_language_list; + +static MPlist *ft_file_list; + +static int all_fonts_scaned; + +#define STRDUP_LOWER(s1, size, s2) \ + do { \ + int len = strlen (s2) + 1; \ + char *p1, *p2; \ + \ + if ((size) < len) \ + (s1) = alloca (len), (size) = len; \ + for (p1 = (s1), p2 = (s2); *p2; p1++, p2++) \ + *p1 = (*p2 >= 'A' && *p2 <= 'Z' ? *p2 + 'a' - 'A' : *p2); \ + *p1 = '\0'; \ + } while (0) + + +static MPlist *ft_list_family (MSymbol, int, int); + +static void +free_ft_rfont (void *object) +{ + MRealizedFontFT *ft_rfont = object; + + if (! ft_rfont->face_encapsulated) + { + M17N_OBJECT_UNREF (ft_rfont->charmap_list); + FT_Done_Face (ft_rfont->ft_face); + } + free (ft_rfont); +} + +static void +free_ft_info (MFontFT *ft_info) +{ +#ifdef HAVE_OTF + if (ft_info->otf && ft_info->otf != invalid_otf) + OTF_close (ft_info->otf); +#endif /* HAVE_OTF */ +#ifdef HAVE_FONTCONFIG + if (ft_info->langset) + FcLangSetDestroy (ft_info->langset); + if (ft_info->charset) + FcCharSetDestroy (ft_info->charset); +#endif /* HAVE_FONTCONFIG */ + free (ft_info); +} + +static MPlist * +ft_get_charmaps (FT_Face ft_face) +{ + MPlist *plist = mplist (); + int unicode_bmp = -1, unicode_full = -1; + int i; + + mplist_add (plist, Mt, (void *) -1); + for (i = 0; i < ft_face->num_charmaps; i++) + { + MSymbol registry = Mnil; + + if (ft_face->charmaps[i]->platform_id == 0) + { + if (ft_face->charmaps[i]->encoding_id <= 4) + registry = M0[ft_face->charmaps[i]->encoding_id], unicode_bmp = i; + if (ft_face->charmaps[i]->encoding_id == 4) + unicode_bmp = unicode_full = i; + } + else if (ft_face->charmaps[i]->platform_id == 3) + { + if (ft_face->charmaps[i]->encoding_id == 1) + registry = M3_1, unicode_bmp = i; + else if (ft_face->charmaps[i]->encoding_id == 10) + unicode_bmp = unicode_full = i; + } + else if (ft_face->charmaps[i]->platform_id == 1 + && ft_face->charmaps[i]->encoding_id == 0) + { + registry = M1_0; + mplist_add (plist, Mapple_roman, (void *) i); + } + if (registry == Mnil) + { + char registry_buf[16]; + + sprintf (registry_buf, "%d-%d", + ft_face->charmaps[i]->platform_id, + ft_face->charmaps[i]->encoding_id); + registry = msymbol (registry_buf); + } + mplist_add (plist, registry, (void *) i); + } + if (unicode_full >= 0) + mplist_add (plist, Municode_full, (void *) unicode_full); + if (unicode_bmp >= 0) + { + int i; + + mplist_add (plist, Municode_bmp, (void *) unicode_bmp); + FT_Set_Charmap (ft_face, ft_face->charmaps[unicode_bmp]); + for (i = 0x21; i < 0x7F && FT_Get_Char_Index (ft_face, i) > 0; i++); + if (i == 0x7F) + { + for (i = 0xC0; i < 0x100 && FT_Get_Char_Index (ft_face, i) > 0; i++); + if (i == 0x100) + mplist_add (plist, Miso8859_1, (void *) unicode_bmp); + } + } + + return plist; +} + +static MFontFT * +ft_gen_font (FT_Face ft_face) +{ + MFontFT *ft_info; + MFont *font; + char *buf; + int bufsize = 0; + char *stylename; + MSymbol family; + int size; + + if (FT_IS_SCALABLE (ft_face)) + size = ft_face->size->metrics.y_ppem; + else if (ft_face->num_fixed_sizes == 0) + return NULL; + else + size = ft_face->available_sizes[0].height; + + MSTRUCT_CALLOC (ft_info, MERROR_FONT_FT); + font = &ft_info->font; + STRDUP_LOWER (buf, bufsize, ft_face->family_name); + family = msymbol (buf); + mfont__set_property (font, MFONT_FAMILY, family); + mfont__set_property (font, MFONT_WEIGHT, Mmedium); + mfont__set_property (font, MFONT_STYLE, Mr); + mfont__set_property (font, MFONT_STRETCH, Mnormal); + mfont__set_property (font, MFONT_ADSTYLE, Mnull); + mfont__set_property (font, MFONT_REGISTRY, Municode_bmp); + font->size = size * 10; + font->type = MFONT_TYPE_OBJECT; + font->source = MFONT_SOURCE_FT; + font->file = NULL; + + stylename = ft_face->style_name; + while (*stylename) + { + int i; + + for (i = 0; i < ft_to_prop_size; i++) + if (! strncasecmp (ft_to_prop[i].ft_style, stylename, + ft_to_prop[i].len)) + { + mfont__set_property (font, ft_to_prop[i].prop, + msymbol (ft_to_prop[i].val)); + stylename += ft_to_prop[i].len; + break; + } + if (i == ft_to_prop_size) + { + char *p1 = stylename + 1; + MSymbol sym; + + while (*p1 >= 'a' && *p1 <= 'z') p1++; + sym = msymbol__with_len (stylename, p1 - stylename); + for (i = MFONT_WEIGHT; i <= MFONT_STRETCH; i++) + if (msymbol_get (sym, mfont__property_table[i].property)) + { + mfont__set_property (font, i, sym); + break; + } + stylename = p1; + } + while (*stylename && ! isalpha (*stylename)) + stylename++; + } + return ft_info; +} + +#ifdef HAVE_FONTCONFIG + +typedef struct +{ + int fc_value; + char *m17n_value; + MSymbol sym; +} FC_vs_M17N_font_prop; + +static FC_vs_M17N_font_prop fc_weight_table[] = + { { FC_WEIGHT_THIN, "thin" }, + { FC_WEIGHT_ULTRALIGHT, "extralight" }, + { FC_WEIGHT_LIGHT, "light" }, +#ifdef FC_WEIGHT_BOOK + { FC_WEIGHT_BOOK, "book" }, +#endif /* FC_WEIGHT_BOOK */ + { FC_WEIGHT_REGULAR, "normal" }, + { FC_WEIGHT_NORMAL, "normal" }, + { FC_WEIGHT_MEDIUM, "medium" }, + { FC_WEIGHT_DEMIBOLD, "demibold" }, + { FC_WEIGHT_BOLD, "bold" }, + { FC_WEIGHT_EXTRABOLD, "extrabold" }, + { FC_WEIGHT_BLACK, "black" }, + { FC_WEIGHT_HEAVY, "heavy" }, + { FC_WEIGHT_MEDIUM, NULL } }; +int fc_weight_table_size = + sizeof fc_weight_table / sizeof (FC_vs_M17N_font_prop); + +static FC_vs_M17N_font_prop fc_slant_table[] = + { { FC_SLANT_ROMAN, "r" }, + { FC_SLANT_ITALIC, "i" }, + { FC_SLANT_OBLIQUE, "o" }, + { FC_SLANT_ROMAN, NULL } }; +int fc_slant_table_size = + sizeof fc_slant_table / sizeof (FC_vs_M17N_font_prop); + +static FC_vs_M17N_font_prop fc_width_table[] = + { { FC_WIDTH_ULTRACONDENSED, "ultracondensed" }, + { FC_WIDTH_EXTRACONDENSED, "extracondensed" }, + { FC_WIDTH_CONDENSED, "condensed" }, + { FC_WIDTH_SEMICONDENSED, "semicondensed" }, + { FC_WIDTH_NORMAL, "normal" }, + { FC_WIDTH_SEMIEXPANDED, "semiexpanded" }, + { FC_WIDTH_EXPANDED, "expanded" }, + { FC_WIDTH_EXTRAEXPANDED, "extraexpanded" }, + { FC_WIDTH_ULTRAEXPANDED, "ultraexpanded" }, + { FC_WIDTH_NORMAL, NULL } }; +int fc_width_table_size = + sizeof fc_width_table / sizeof (FC_vs_M17N_font_prop); + + +static FC_vs_M17N_font_prop *fc_all_table[] = + { fc_weight_table, fc_slant_table, fc_width_table }; + +static MSymbol +fc_decode_prop (int val, FC_vs_M17N_font_prop *table, int size) +{ + int i = size / 2; + + if (val < table[i].fc_value) + { + for (i--; i >= 0; i--) + if (val > table[i].fc_value) + break; + i++; + } + else if (val > table[i].fc_value) + { + for (i++; i < size; i++) + if (val < table[i].fc_value) + break; + i--; + } + return table[i].sym; +} + +static int +fc_encode_prop (MSymbol sym, FC_vs_M17N_font_prop *table) +{ + int i; + + for (i = 0; table[i].m17n_value; i++) + if (table[i].sym == sym) + break; + return table[i].fc_value; +} + +FcPattern * +fc_get_pattern (MFont *font) +{ + FcPattern *pat = FcPatternCreate (); + MSymbol sym, weight, style, stretch; + + + if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FOUNDRY)) != Mnil) + FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) MSYMBOL_NAME (sym)); + if ((sym = (MSymbol) FONT_PROPERTY (font, MFONT_FAMILY)) != Mnil) + FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) MSYMBOL_NAME (sym)); + if ((weight = (MSymbol) FONT_PROPERTY (font, MFONT_WEIGHT)) != Mnil) + FcPatternAddInteger (pat, FC_WEIGHT, + fc_encode_prop (weight, fc_weight_table)); + if ((style = (MSymbol) FONT_PROPERTY (font, MFONT_STYLE)) != Mnil) + FcPatternAddInteger (pat, FC_SLANT, + fc_encode_prop (style, fc_slant_table)); + if ((stretch = (MSymbol) FONT_PROPERTY (font, MFONT_STRETCH)) != Mnil) + FcPatternAddInteger (pat, FC_WIDTH, + fc_encode_prop (stretch, fc_width_table)); + if (font->size > 0) + { + double size = font->size; + FcPatternAddDouble (pat, FC_PIXEL_SIZE, size / 10); + } + else if (font->size < 0) + { + double size = - font->size; + FcPatternAddDouble (pat, FC_SIZE, size / 10); + } + return pat; +} + +static void +fc_parse_pattern (FcPattern *pat, char *family, MFontFT *ft_info) +{ + FcChar8 *str; + int val; + double size; + char *buf; + int bufsize = 0; + MSymbol sym; + FcLangSet *ls; + FcCharSet *cs; + MFont *font = &ft_info->font; + + MFONT_INIT (font); + if (FcPatternGetString (pat, FC_FOUNDRY, 0, &str) == FcResultMatch) + { + STRDUP_LOWER (buf, bufsize, (char *) str); + mfont__set_property (font, MFONT_FOUNDRY, msymbol (buf)); + } + if (family) + mfont__set_property (font, MFONT_FAMILY, msymbol (family)); + else if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch) + { + STRDUP_LOWER (buf, bufsize, (char *) str); + mfont__set_property (font, MFONT_FAMILY, msymbol (buf)); + } + if (FcPatternGetInteger (pat, FC_WEIGHT, 0, &val) == FcResultMatch) + { + sym = fc_decode_prop (val, fc_weight_table, fc_weight_table_size); + mfont__set_property (font, MFONT_WEIGHT, sym); + } + if (FcPatternGetInteger (pat, FC_SLANT, 0, &val) == FcResultMatch) + { + sym = fc_decode_prop (val, fc_slant_table, fc_slant_table_size); + mfont__set_property (font, MFONT_STYLE, sym); + } + if (FcPatternGetInteger (pat, FC_WIDTH, 0, &val) == FcResultMatch) + { + sym = fc_decode_prop (val, fc_width_table, fc_width_table_size); + mfont__set_property (font, MFONT_STRETCH, sym); + } + if (FcPatternGetLangSet (pat, FC_LANG, 0, &ls) == FcResultMatch) + { + if (FcLangSetHasLang (ls, (FcChar8 *) "ja") != FcLangDifferentLang + || FcLangSetHasLang (ls, (FcChar8 *) "zh") != FcLangDifferentLang + || FcLangSetHasLang (ls, (FcChar8 *) "ko") != FcLangDifferentLang) + font->for_full_width = 1; + ft_info->langset = FcLangSetCopy (ls); + } + if (FcPatternGetCharSet (pat, FC_CHARSET, 0, &cs) == FcResultMatch) + ft_info->charset = FcCharSetCopy (cs); + + mfont__set_property (font, MFONT_REGISTRY, Municode_bmp); + font->type = MFONT_TYPE_SPEC; + font->source = MFONT_SOURCE_FT; + if (FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &size) == FcResultMatch) + font->size = size * 10; + if (FcPatternGetString (pat, FC_FILE, 0, &str) == FcResultMatch) + font->file = msymbol ((char *) str); +} + + +static MFontFT * +fc_gen_font (FcPattern *pat, char *family) +{ + MFontFT *ft_info; + + MSTRUCT_CALLOC (ft_info, MERROR_FONT_FT); + fc_parse_pattern (pat, family, ft_info); + ft_info->font.type = MFONT_TYPE_OBJECT; + return ft_info; +} + +static void +fc_init_font_list (void) +{ + FcPattern *pattern = FcPatternCreate (); + FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, NULL); + FcFontSet *fs = FcFontList (fc_config, pattern, os); + MPlist *plist = mplist (); + char *buf; + int bufsize = 0; + int i; + + ft_font_list = plist; + for (i = 0; i < fs->nfont; i++) + { + char *fam; + + if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0, + (FcChar8 **) &fam) != FcResultMatch) + continue; + STRDUP_LOWER (buf, bufsize, fam); + plist = mplist_add (plist, msymbol (buf), NULL); + } + FcFontSetDestroy (fs); + FcObjectSetDestroy (os); + FcPatternDestroy (pattern); +} + +static MPlist * +fc_list_pattern (FcPattern *pattern) +{ + FcObjectSet *os = NULL; + FcFontSet *fs = NULL; + MSymbol last_family = Mnil; + MPlist *plist = NULL, *pl = NULL; + char *buf; + int bufsize = 0; + int i; + + if (! (os = FcObjectSetBuild (FC_FAMILY, FC_FILE, NULL))) + goto err; + if (! (fs = FcFontList (fc_config, pattern, os))) + goto err; + + for (i = 0; i < fs->nfont; i++) + { + MSymbol family, file; + char *fam, *filename; + MFontFT *ft_info; + + if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0, + (FcChar8 **) &fam) != FcResultMatch) + continue; + if (FcPatternGetString (fs->fonts[i], FC_FILE, 0, + (FcChar8 **) &filename) != FcResultMatch) + continue; + STRDUP_LOWER (buf, bufsize, fam); + family = msymbol (buf); + file = msymbol (filename); + if (family != last_family) + { + pl = MPLIST_PLIST (ft_list_family (family, 0, 1)); + last_family = family; + } + ft_info = mplist_get (pl, file); + if (ft_info) + { + if (! plist) + plist = mplist (); + mplist_add (plist, family, ft_info); + } + } + + err: + if (fs) FcFontSetDestroy (fs); + if (os) FcObjectSetDestroy (os); + return plist; +} + +/* Return FcCharSet object built from CHAR_LIST or MT. In the latter + case, it is assured that the M-text contains at least one + character. */ + +static FcCharSet * +fc_build_charset (MPlist *char_list, MText *mt) +{ + FcCharSet *cs = FcCharSetCreate (); + + if (! cs) + return NULL; + if (char_list) + { + for (; ! MPLIST_TAIL_P (char_list); char_list = MPLIST_NEXT (char_list)) + if (! FcCharSetAddChar (cs, (FcChar32) MPLIST_INTEGER (char_list))) + { + FcCharSetDestroy (cs); + return NULL; + } + } + else + { + int i; + + for (i = mtext_nchars (mt) - 1; i >= 0; i--) + if (! FcCharSetAddChar (cs, (FcChar32) mtext_ref_char (mt, i))) + { + FcCharSetDestroy (cs); + return NULL; + } + if (mtext_nchars (mt) > 0 + && (mt = mtext_get_prop (mt, 0, Mtext))) + for (i = mtext_nchars (mt) - 1; i >= 0; i--) + if (! FcCharSetAddChar (cs, (FcChar32) mtext_ref_char (mt, i))) + { + FcCharSetDestroy (cs); + return NULL; + } + } + return cs; +} + +#else /* not HAVE_FONTCONFIG */ + +static MPlist * +ft_add_font (char *filename) +{ + FT_Face ft_face; + char *stylename; + int size = 0; + MSymbol family; + MFontFT *ft_info; + MFont *font; + MPlist *plist; + int i; + char *buf; + int bufsize = 0; + + if (FT_New_Face (ft_library, filename, 0, &ft_face) != 0) + return NULL; + ft_info = ft_gen_font (ft_face); + FT_Done_Face (ft_face); + if (! ft_info) + return NULL; + + font = &ft_info->font; + font->file = msymbol (filename); + + plist = mplist_find_by_key (ft_font_list, family); + if (plist) + mplist_push (MPLIST_PLIST (plist), font->file, ft_info); + else + { + plist = mplist (); + mplist_add (plist, font->file, ft_info); + plist = mplist_push (ft_font_list, family, plist); + } + return plist; +} + +static void +ft_init_font_list (void) +{ + MPlist *plist; + struct stat buf; + char *pathname; + char *path; + USE_SAFE_ALLOCA; + + ft_font_list = mplist (); + MPLIST_DO (plist, mfont_freetype_path) + if (MPLIST_STRING_P (plist) + && (pathname = MPLIST_STRING (plist)) + && stat (pathname, &buf) == 0) + { + if (S_ISREG (buf.st_mode)) + ft_add_font (pathname); + else if (S_ISDIR (buf.st_mode)) + { + DIR *dir = opendir (pathname); + + if (dir) + { + int len = strlen (pathname); + struct dirent *dp; + + while ((dp = readdir (dir)) != NULL) + { + SAFE_ALLOCA (path, len + strlen (dp->d_name) + 2); + strcpy (path, pathname); + path[len] = '/'; + strcpy (path + len + 1, dp->d_name); + ft_add_font (path); + } + closedir (dir); + } + } + } + SAFE_FREE (path); +} + +/* Return 1 iff the font pointed by FT_INFO has all characters in + CHAR_LIST. */ + +static int +ft_has_char_list_p (MFontFT *ft_info, MPlist *char_list) +{ + FT_Face ft_face; + MPlist *cl; + + if (FT_New_Face (ft_library, MSYMBOL_NAME (ft_info->font.file), 0, &ft_face)) + return 0; + MPLIST_DO (cl, char_list) + if (FT_Get_Char_Index (ft_face, (FT_ULong) MPLIST_INTEGER (cl)) == 0) + break; + FT_Done_Face (ft_face); + return MPLIST_TAIL_P (cl); +} + +/* Return ((FAMILY . FONT) ...) where FONT is a pointer to MFontFT + that supports characters in CHAR_LIST or MT. One of CHAR_LIST or + MT must be NULL. */ + +static MPlist * +ft_list_char_list (MPlist *char_list, MText *mt) +{ + MPlist *plist = NULL, *pl, *p; + + if (! ft_font_list) + ft_list_family (Mnil, 0, 1); + + if (mt) + { + int len = mtext_nchars (mt); + MText *extra = mtext_get_prop (mt, 0, Mtext); + int total_len = len + (extra ? mtext_nchars (extra) : 0); + int i; + + char_list = mplist (); + for (i = 0; i < total_len; i++) + { + int c = (i < len ? mtext_ref_char (mt, i) + : mtext_ref_char (extra, i - len)); + + if (! mplist_find_by_value (char_list, (void *) c)) + mplist_push (char_list, Minteger, (void *) c); + } + } + + MPLIST_DO (pl, ft_font_list) + { + MPLIST_DO (p, MPLIST_PLIST (pl)) + { + MFontFT *ft_info = MPLIST_VAL (p); + + if (ft_has_char_list_p (ft_info, char_list)) + { + MSymbol family = mfont_get_prop (&ft_info->font, Mfamily); + + if (! plist) + plist = mplist (); + mplist_push (plist, family, ft_info); + } + } + } + if (mt) + M17N_OBJECT_UNREF (char_list); + return plist; +} +#endif /* not HAVE_FONTCONFIG */ + + +/* Return an element of ft_font_list for FAMILY. If FAMILY is Mnil, + scan all fonts and return ft_font_list. */ + +static MPlist * +ft_list_family (MSymbol family, int check_generic, int check_alias) +{ + MPlist *plist; +#ifdef HAVE_FONTCONFIG + char *fam; + MPlist *pl, *p; + FcPattern *pattern; + FcObjectSet *os; + FcFontSet *fs; + int i; + char *buf; + int bufsize = 0; + MSymbol generic; + + if (! ft_font_list) + { + MSymbol sym; + + plist = ft_font_list = mplist (); + pattern = FcPatternCreate (); + os = FcObjectSetBuild (FC_FAMILY, NULL); + fs = FcFontList (fc_config, pattern, os); + for (i = 0; i < fs->nfont; i++) + { + if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0, + (FcChar8 **) &fam) != FcResultMatch) + continue; + STRDUP_LOWER (buf, bufsize, fam); + sym = msymbol (buf); + if (! mplist_find_by_key (ft_font_list, sym)) + plist = mplist_add (plist, sym, NULL); + } + FcFontSetDestroy (fs); + FcObjectSetDestroy (os); + FcPatternDestroy (pattern); + } + + if (family == Mnil) + { + if (! all_fonts_scaned) + { + MPLIST_DO (plist, ft_font_list) + { + if (! MPLIST_VAL (plist)) + ft_list_family (MPLIST_KEY (plist), 0, 1); + } + all_fonts_scaned = 1; + } + return ft_font_list; + } + + plist = mplist_find_by_key (ft_font_list, family); + if (plist) + { + if (! MPLIST_VAL (plist)) + { + fam = MSYMBOL_NAME (family); + pattern = FcPatternCreate (); + FcPatternAddString (pattern, FC_FAMILY, (FcChar8 *) fam); + os = FcObjectSetBuild (FC_FOUNDRY, FC_WEIGHT, FC_SLANT, FC_WIDTH, + FC_PIXEL_SIZE, FC_LANG, FC_CHARSET, FC_FILE, + NULL); + fs = FcFontList (fc_config, pattern, os); + p = pl = mplist (); + for (i = 0; i < fs->nfont; i++) + { + MFontFT *ft_info = fc_gen_font (fs->fonts[i], fam); + p = mplist_add (p, ft_info->font.file, ft_info); + } + MPLIST_VAL (plist) = pl; + FcFontSetDestroy (fs); + FcObjectSetDestroy (os); + FcPatternDestroy (pattern); + } + } + else if (check_generic + && (generic = msymbol_get (family, Mgeneric_family)) != Mnil) + { + /* Check if FAMILY is a geneneric family (e.g. `serif'). */ + FcChar8 *fam8; + + if (family != generic) + plist = ft_list_family (generic, 1, 1); + else + { + fam = MSYMBOL_NAME (family); + plist = mplist (); + mplist_push (ft_font_list, family, plist); + pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, fam, NULL); + FcConfigSubstitute (fc_config, pattern, FcMatchPattern); + for (i = 0; 1; i++) + { + if (FcPatternGetString (pattern, FC_FAMILY, i, &fam8) + != FcResultMatch) + break; + STRDUP_LOWER (buf, bufsize, (char *) fam8); + family = msymbol (buf); + if (msymbol_get (family, Mgeneric_family)) + break; + pl = ft_list_family (family, 0, 1); + if (! pl) + continue; + MPLIST_DO (pl, MPLIST_PLIST (pl)) + plist = mplist_add (plist, Mt, MPLIST_VAL (pl)); + } + plist = ft_font_list; + } + } + else if (check_alias) + { + /* Check if there exist an alias. */ + pl = mplist (); + plist = mplist_add (ft_font_list, family, pl); + + pattern = FcPatternBuild (NULL, + FC_FAMILY, FcTypeString, MSYMBOL_NAME (family), + NULL); + FcConfigSubstitute (fc_config, pattern, FcMatchPattern); + + for (i = 0; FcPatternGetString (pattern, FC_FAMILY, i, + (FcChar8 **) &fam) == FcResultMatch; + i++); + if (i > 0) + { + /* The last one is a generic family. */ + MSymbol sym; + int j; + FcPattern *pat = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, fam, + NULL); + + FcConfigSubstitute (fc_config, pat, FcMatchPattern); + for (j = 0; FcPatternGetString (pat, FC_FAMILY, j, + (FcChar8 **) &fam) == FcResultMatch; + j++); + + /* Now we know that the last J fonts in PATTERN are from + generic font, and the first one is not available. So, + the remaining ones are aliases. */ + j = i - j; + for (i = 1; i < j; i++) + { + FcPatternGetString (pattern, FC_FAMILY, i, (FcChar8 **) &fam); + STRDUP_LOWER (buf, bufsize, fam); + sym = msymbol (buf); + p = MPLIST_PLIST (ft_list_family (sym, 0, 0)); + if (! MPLIST_TAIL_P (p)) + MPLIST_DO (p, p) + mplist_push (pl, Mt, MPLIST_VAL (p)); + } + } + } + else + { + pl = mplist (); + plist = mplist_add (ft_font_list, family, pl); + } + +#else /* not HAVE_FONTCONFIG */ + + if (! all_fonts_scaned) + { + ft_init_font_list (); + all_fonts_scaned = 1; + } + if (family == Mnil) + plist = ft_font_list; + else + { + plist = mplist_find_by_key (ft_font_list, family); + if (! plist) + plist = mplist_push (ft_font_list, family, mplist ()); + } +#endif /* not HAVE_FONTCONFIG */ + + return plist; +} + +static MPlist * +ft_list_language (MSymbol language) +{ + MPlist *plist = NULL; + MText *mt; + + if (! ft_language_list) + ft_language_list = mplist (); + else if ((plist = mplist_find_by_key (ft_language_list, language))) + return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL); + + mt = mlanguage_text (language); + +#ifdef HAVE_FONTCONFIG + { + FcPattern *pattern = NULL; + FcCharSet *cs = NULL; + FcLangSet *ls = NULL; + + if (! (pattern = FcPatternCreate ())) + goto err; + + if (mt && mtext_nchars (mt) > 0) + { + cs = fc_build_charset (NULL, mt); + if (cs && ! FcPatternAddCharSet (pattern, FC_CHARSET, cs)) + goto err; + } + else + { + if (! (ls = FcLangSetCreate ())) + goto err; + if (! FcLangSetAdd (ls, (FcChar8 *) MSYMBOL_NAME (language)) + || ! FcPatternAddLangSet (pattern, FC_LANG, ls)) + goto err; + } + + plist = fc_list_pattern (pattern); + err: + if (cs) FcCharSetDestroy (cs); + if (ls) FcLangSetDestroy (ls); + if (pattern) FcPatternDestroy (pattern); + } +#else /* not HAVE_FONTCONFIG */ + if (mt && mtext_nchars (mt) > 0) + plist = ft_list_char_list (NULL, mt); +#endif /* not HAVE_FONTCONFIG */ + + mplist_push (ft_language_list, language, plist); + return plist; +} + +static MPlist * +ft_list_script (MSymbol script) +{ + MPlist *plist = NULL; + MPlist *char_list; + + if (! ft_script_list) + ft_script_list = mplist (); + else if ((plist = mplist_find_by_key (ft_script_list, script))) + return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL); + + char_list = mscript__char_list (script); + +#ifdef HAVE_FONTCONFIG + if (char_list) + { + FcPattern *pattern = NULL; + FcCharSet *cs; + + if (! (pattern = FcPatternCreate ())) + goto err; + cs = fc_build_charset (char_list, NULL); + if (cs && ! FcPatternAddCharSet (pattern, FC_CHARSET, cs)) + goto err; + plist = fc_list_pattern (pattern); + err: + if (cs) FcCharSetDestroy (cs); + if (pattern) FcPatternDestroy (pattern); + } +#else /* not HAVE_FONTCONFIG */ + if (char_list) + plist = ft_list_char_list (char_list, NULL); +#endif /* not HAVE_FONTCONFIG */ + + mplist_push (ft_script_list, script, plist); + return (plist); +} + +static int +ft_check_cap_otf (MFontFT *ft_info, MFontCapability *cap, FT_Face ft_face) +{ +#ifdef HAVE_OTF + if (ft_info->otf == invalid_otf) + return -1; + if (! ft_info->otf) + { +#if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4) + if (ft_face) + ft_info->otf = OTF_open_ft_face (ft_face); + else +#endif + ft_info->otf = OTF_open (MSYMBOL_NAME (ft_info->font.file)); + if (! ft_info->otf) + { + ft_info->otf = invalid_otf; + return -1; + } + } + if (cap->features[MFONT_OTT_GSUB].nfeatures + && (OTF_check_features + (ft_info->otf, 1, + cap->script_tag, cap->langsys_tag, + cap->features[MFONT_OTT_GSUB].tags, + cap->features[MFONT_OTT_GSUB].nfeatures) != 1)) + return -1; + if (cap->features[MFONT_OTT_GPOS].nfeatures + && (OTF_check_features + (ft_info->otf, 0, + cap->script_tag, cap->langsys_tag, + cap->features[MFONT_OTT_GPOS].tags, + cap->features[MFONT_OTT_GPOS].nfeatures) != 1)) + return -1; + return 0; +#else /* not HAVE_OTF */ + return -1; +#endif /* not HAVE_OTF */ +} + +static int +ft_check_language (MFontFT *ft_info, MSymbol language, FT_Face ft_face) +{ + MText *mt; + MText *extra; + int ft_face_allocaed = 0; + int len, total_len; + int i; + +#ifdef HAVE_FONTCONFIG + if (ft_info->langset + && (FcLangSetHasLang (ft_info->langset, + (FcChar8 *) MSYMBOL_NAME (language)) + != FcLangDifferentLang)) + return 0; +#endif /* HAVE_FONTCONFIG */ + + mt = mlanguage_text (language); + if (! mt || mtext_nchars (mt) == 0) + return -1; + + if (! ft_face) + { + char *filename = MSYMBOL_NAME (ft_info->font.file); + + if (FT_New_Face (ft_library, filename, 0, &ft_face)) + return -1; + ft_face_allocaed = 1; + } + + len = mtext_nchars (mt); + extra = mtext_get_prop (mt, 0, Mtext); + total_len = len + (extra ? mtext_nchars (extra) : 0); + + for (i = 0; i < total_len; i++) + { + int c = (i < len ? mtext_ref_char (mt, i) + : mtext_ref_char (extra, i - len)); + +#ifdef HAVE_FONTCONFIG + if (ft_info->charset + && FcCharSetHasChar (ft_info->charset, (FcChar32) c) == FcFalse) + break; +#endif /* HAVE_FONTCONFIG */ + if (FT_Get_Char_Index (ft_face, (FT_ULong) c) == 0) + break; + } + + if (ft_face_allocaed) + FT_Done_Face (ft_face); + + return (i == total_len ? 0 : -1); +} + +static int +ft_check_script (MFontFT *ft_info, MSymbol script, FT_Face ft_face) +{ + MPlist *char_list = mscript__char_list (script); + + if (! char_list) + return -1; +#ifdef HAVE_FONTCONFIG + if (ft_info->charset) + { + MPLIST_DO (char_list, char_list) + if (FcCharSetHasChar (ft_info->charset, + (FcChar32) MPLIST_INTEGER (char_list)) == FcFalse) + break; + } + else +#endif /* HAVE_FONTCONFIG */ + { + int ft_face_allocaed = 0; + + if (! ft_face) + { + char *filename = MSYMBOL_NAME (ft_info->font.file); + + if (FT_New_Face (ft_library, filename, 0, &ft_face)) + return -1; + ft_face_allocaed = 1; + } + + MPLIST_DO (char_list, char_list) + if (FT_Get_Char_Index (ft_face, (FT_ULong) MPLIST_INTEGER (char_list)) + == 0) + break; + if (ft_face_allocaed) + FT_Done_Face (ft_face); + } + + return (MPLIST_TAIL_P (char_list) ? 0 : -1); +} + +static MPlist *ft_default_list; + +static MPlist * +ft_list_default () +{ + if (ft_default_list) + return ft_default_list; + ft_default_list = mplist (); +#ifdef HAVE_FONTCONFIG + { + FcPattern *pat = FcPatternCreate (); + FcChar8 *fam; + char *buf; + int bufsize = 0; + int i; + + FcConfigSubstitute (fc_config, pat, FcMatchPattern); + for (i = 0; FcPatternGetString (pat, FC_FAMILY, i, &fam) == FcResultMatch; + i++) + { + MSymbol family; + MPlist *plist; + + STRDUP_LOWER (buf, bufsize, (char *) fam); + family = msymbol (buf); + if (msymbol_get (family, Mgeneric_family)) + continue; + plist = MPLIST_PLIST (ft_list_family (family, 0, 1)); + MPLIST_DO (plist, plist) + mplist_add (ft_default_list, family, MPLIST_VAL (plist)); + } + } +#else /* not HAVE_FONTCONFIG */ + { + MPlist *plist, *pl; + + MPLIST_DO (plist, ft_list_family (Mnil, 0, 1)) + { + pl = MPLIST_PLIST (plist); + if (! MPLIST_TAIL_P (pl)) + mplist_add (ft_default_list, MPLIST_KEY (plist), pl); + } + } +#endif /* not HAVE_FONTCONFIG */ + return ft_default_list; +} + + +static MPlist *ft_capability_list; + +static MPlist * +ft_list_capability (MSymbol capability) +{ + MFontCapability *cap; + MPlist *plist = NULL, *pl; + + if (! ft_capability_list) + ft_capability_list = mplist (); + else if ((plist = mplist_find_by_key (ft_capability_list, capability))) + return (MPLIST_VAL (plist) ? MPLIST_VAL (plist) : NULL); + + cap = mfont__get_capability (capability); + + if (cap && cap->language != Mnil) + { + plist = ft_list_language (cap->language); + if (! plist) + return NULL; + plist = mplist_copy (plist); + } + + if (cap && cap->script != Mnil) + { + if (! plist) + { + plist = ft_list_script (cap->script); + if (! plist) + return NULL; + plist = mplist_copy (plist); + } + else + { + for (pl = plist; ! MPLIST_TAIL_P (pl);) + { + if (ft_check_script (MPLIST_VAL (pl), cap->script, NULL) < 0) + mplist_pop (pl); + else + pl = MPLIST_NEXT (pl); + } + } + + if (cap->script_tag) + { + for (pl = plist; ! MPLIST_TAIL_P (pl);) + { + if (ft_check_cap_otf (MPLIST_VAL (pl), cap, NULL) < 0) + mplist_pop (pl); + else + pl = MPLIST_NEXT (pl); + } + } + + if (MPLIST_TAIL_P (plist)) + { + M17N_OBJECT_UNREF (plist); + plist = NULL; + } + } + + mplist_push (ft_capability_list, capability, plist); + return plist; +} + + +static MPlist * +ft_list_file (MSymbol filename) +{ + MPlist *plist = NULL; + + if (! ft_file_list) + ft_file_list = mplist (); + else if ((plist = mplist_find_by_key (ft_file_list, filename))) + return (MPLIST_VAL (plist) ? MPLIST_PLIST (plist) : NULL); + +#ifdef HAVE_FONTCONFIG + { + FcPattern *pattern = FcPatternCreate (); + FcObjectSet *os; + FcFontSet *fs; + + FcPatternAddString (pattern, FC_FILE, (FcChar8 *) MSYMBOL_NAME (filename)); + os = FcObjectSetBuild (FC_FAMILY, NULL); + fs = FcFontList (fc_config, pattern, os); + if (fs->nfont > 0) + { + char *fam; + char *buf; + int bufsize = 0; + + if (FcPatternGetString (fs->fonts[0], FC_FAMILY, 0, + (FcChar8 **) &fam) == FcResultMatch) + { + MSymbol family; + MPlist *pl; + + STRDUP_LOWER (buf, bufsize, fam); + family = msymbol (buf); + pl = ft_list_family (family, 0, 1); + MPLIST_DO (pl, MPLIST_PLIST (pl)) + { + MFontFT *ft_info = MPLIST_VAL (pl); + + if (ft_info->font.file == filename) + { + plist = mplist (); + mplist_add (plist, family, ft_info); + break; + } + } + } + } + } +#else /* not HAVE_FONTCONFIG */ + { + MPlist *pl, *p; + + MPLIST_DO (pl, ft_list_family (Mnil, 0, 1)) + { + MPLIST_DO (p, MPLIST_PLIST (pl)) + { + MFontFT *ft_info = MPLIST_VAL (pl); + + if (ft_info->font.file == filename) + { + plist = mplist (); + mplist_add (plist, MPLIST_KEY (pl), ft_info); + break; + } + } + if (plist) + break; + } + } +#endif /* not HAVE_FONTCONFIG */ + + mplist_push (ft_file_list, filename, plist); + return plist; +} + +/* The FreeType font driver function SELECT. */ + +static MFont * +ft_select (MFrame *frame, MFont *font, int limited_size) +{ + MFont *found = NULL; +#ifdef HAVE_FONTCONFIG + MPlist *plist, *pl; + MFontFT *ft_info; + int check_font_property = 1; + + if (font->file != Mnil) + { + plist = ft_list_file (font->file); + if (! plist) + return NULL; + check_font_property = 0; + } + else + { + MSymbol family = FONT_PROPERTY (font, MFONT_FAMILY); + + if (family) + plist = MPLIST_PLIST (ft_list_family (family, 1, 1)); + else + plist = ft_list_default (); + if (MPLIST_TAIL_P (plist)) + return NULL; + } + + plist = mplist_copy (plist); + + if (font->capability != Mnil) + { + MFontCapability *cap = mfont__get_capability (font->capability); + + for (pl = plist; ! MPLIST_TAIL_P (pl);) + { + if (cap->script_tag && ft_check_cap_otf (MPLIST_VAL (pl), cap, NULL) < 0) + { + mplist_pop (pl); + continue; + } + if (cap->language + && ft_check_language (MPLIST_VAL (pl), cap->language, NULL) < 0) + mplist_pop (pl); + else + pl = MPLIST_NEXT (pl); + } + } + + if (check_font_property) + { + MSymbol weight = FONT_PROPERTY (font, MFONT_WEIGHT); + MSymbol style = FONT_PROPERTY (font, MFONT_STYLE); + MSymbol stretch = FONT_PROPERTY (font, MFONT_STRETCH); + MSymbol alternate_weight = Mnil; + + if (weight == Mnormal) + alternate_weight = Mmedium; + else if (weight == Mmedium) + alternate_weight = Mnormal; + if (weight != Mnil || style != Mnil || stretch != Mnil || font->size > 0) + for (pl = plist; ! MPLIST_TAIL_P (pl); ) + { + ft_info = MPLIST_VAL (pl); + if ((weight != Mnil + && (weight != FONT_PROPERTY (&ft_info->font, MFONT_WEIGHT) + && alternate_weight != FONT_PROPERTY (&ft_info->font, MFONT_WEIGHT))) + || (style != Mnil + && style != FONT_PROPERTY (&ft_info->font, MFONT_STYLE)) + || (stretch != Mnil + && stretch != FONT_PROPERTY (&ft_info->font, + MFONT_STRETCH)) + || (font->size > 0 + && ft_info->font.size > 0 + && ft_info->font.size != font->size)) + mplist_pop (pl); + else + pl = MPLIST_NEXT (pl); + } + } + + MPLIST_DO (pl, plist) + { + font = MPLIST_VAL (plist); + if (limited_size == 0 + || font->size == 0 + || font->size <= limited_size) + { + found = font; + break; + } + } + M17N_OBJECT_UNREF (plist); +#endif /* HAVE_FONTCONFIG */ + return found; +} + + +static MRealizedFont * +ft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont) +{ + MFontFT *ft_info = (MFontFT *) font; + int reg = spec->property[MFONT_REGISTRY]; + MSymbol registry = FONT_PROPERTY (spec, MFONT_REGISTRY); + MRealizedFontFT *ft_rfont; + FT_Face ft_face; + MPlist *plist, *charmap_list = NULL; + int charmap_index; + int size; + + if (font->size) + /* non-scalable font */ + size = font->size; + else if (spec->size) + { + int ratio = mfont_resize_ratio (font); + + size = ratio == 100 ? spec->size : spec->size * ratio / 100; + } + else + size = 120; + + if (rfont) + { + charmap_list = ((MRealizedFontFT *) rfont->info)->charmap_list; + for (; rfont; rfont = rfont->next) + if (rfont->font == font + && (rfont->font->size ? rfont->font->size == size + : rfont->spec.size == size) + && rfont->spec.property[MFONT_REGISTRY] == reg + && rfont->driver == &mfont__ft_driver) + return rfont; + } + + MDEBUG_DUMP (" [FONT-FT] opening ", "", mdebug_dump_font (&ft_info->font)); + + if (FT_New_Face (ft_library, MSYMBOL_NAME (ft_info->font.file), 0, + &ft_face)) + { + font->type = MFONT_TYPE_FAILURE; + MDEBUG_PRINT (" no (FT_New_Face)\n"); + return NULL; + } + if (charmap_list) + M17N_OBJECT_REF (charmap_list); + else + charmap_list = ft_get_charmaps (ft_face); + if (registry == Mnil) + registry = Municode_bmp; + plist = mplist_find_by_key (charmap_list, registry); + if (! plist) + { + FT_Done_Face (ft_face); + M17N_OBJECT_UNREF (charmap_list); + MDEBUG_PRINT1 (" no (%s)\n", MSYMBOL_NAME (registry)); + return NULL; + } + charmap_index = (int) MPLIST_VAL (plist); + if ((charmap_index >= 0 + && FT_Set_Charmap (ft_face, ft_face->charmaps[charmap_index])) + || FT_Set_Pixel_Sizes (ft_face, 0, size / 10)) + { + FT_Done_Face (ft_face); + M17N_OBJECT_UNREF (charmap_list); + font->type = MFONT_TYPE_FAILURE; + MDEBUG_PRINT1 (" no (size %d)\n", size); + return NULL; + } + + M17N_OBJECT (ft_rfont, free_ft_rfont, MERROR_FONT_FT); + ft_rfont->ft_face = ft_face; + ft_rfont->charmap_list = charmap_list; + MSTRUCT_CALLOC (rfont, MERROR_FONT_FT); + rfont->id = ft_info->font.file; + rfont->spec = *font; + rfont->spec.type = MFONT_TYPE_REALIZED; + rfont->spec.property[MFONT_REGISTRY] = reg; + rfont->spec.size = size; + rfont->frame = frame; + rfont->font = font; + rfont->driver = &mfont__ft_driver; + rfont->info = ft_rfont; + rfont->fontp = ft_face; + rfont->ascent = ft_face->size->metrics.ascender; + rfont->descent = - ft_face->size->metrics.descender; + rfont->max_advance = ft_face->size->metrics.max_advance; + rfont->baseline_offset = 0; + rfont->x_ppem = ft_face->size->metrics.x_ppem; + rfont->y_ppem = ft_face->size->metrics.y_ppem; +#ifdef HAVE_FTBDF_H + { + BDF_PropertyRec prop; + + if (! FT_IS_SCALABLE (ft_face) + && FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &prop) == 0) + { + rfont->baseline_offset = prop.u.integer << 6; + rfont->ascent += prop.u.integer << 6; + rfont->descent -= prop.u.integer << 6; + } + } +#endif /* HAVE_FTBDF_H */ + if (FT_IS_SCALABLE (ft_face)) + rfont->average_width = 0; + else + rfont->average_width = ft_face->available_sizes->width << 6; + rfont->next = MPLIST_VAL (frame->realized_font_list); + MPLIST_VAL (frame->realized_font_list) = rfont; + MDEBUG_PRINT (" ok\n"); + return rfont; +} + +/* The FreeType font driver function FIND_METRIC. */ + +static void +ft_find_metric (MRealizedFont *rfont, MGlyphString *gstring, + int from, int to) +{ + FT_Face ft_face = rfont->fontp; + MGlyph *g = MGLYPH (from), *gend = MGLYPH (to); + + for (; g != gend; g++) + { + if (g->g.measured) + continue; + if (g->g.code == MCHAR_INVALID_CODE) + { + if (FT_IS_SCALABLE (ft_face)) + { + g->g.lbearing = 0; + g->g.rbearing = ft_face->size->metrics.max_advance; + g->g.xadv = g->g.rbearing; + g->g.ascent = ft_face->size->metrics.ascender; + g->g.descent = - ft_face->size->metrics.descender; + } + else + { +#ifdef HAVE_FTBDF_H + BDF_PropertyRec prop; +#endif /* HAVE_FTBDF_H */ + + g->g.lbearing = 0; + g->g.rbearing = g->g.xadv = ft_face->available_sizes->width << 6; +#ifdef HAVE_FTBDF_H + if (FT_Get_BDF_Property (ft_face, "ASCENT", &prop) == 0) + { + g->g.ascent = prop.u.integer << 6; + FT_Get_BDF_Property (ft_face, "DESCENT", &prop); + g->g.descent = prop.u.integer << 6; + if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", + & prop) == 0) + { + g->g.ascent += prop.u.integer << 6; + g->g.descent -= prop.u.integer << 6; + } + } + else +#endif /* HAVE_FTBDF_H */ + { + g->g.ascent = ft_face->available_sizes->height << 6; + g->g.descent = 0; + } + } + } + else + { + FT_Glyph_Metrics *metrics; + + FT_Load_Glyph (ft_face, (FT_UInt) g->g.code, FT_LOAD_DEFAULT); + metrics = &ft_face->glyph->metrics; + g->g.lbearing = metrics->horiBearingX; + g->g.rbearing = metrics->horiBearingX + metrics->width; + g->g.xadv = metrics->horiAdvance; + g->g.ascent = metrics->horiBearingY; + g->g.descent = metrics->height - metrics->horiBearingY; + } + g->g.yadv = 0; + g->g.ascent += rfont->baseline_offset; + g->g.descent -= rfont->baseline_offset; + g->g.measured = 1; + } +} + +static int +ft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code) +{ + MRealizedFont *rfont = NULL; + MRealizedFontFT *ft_rfont; + FT_UInt idx; + + if (font->type == MFONT_TYPE_REALIZED) + rfont = (MRealizedFont *) font; + else if (font->type == MFONT_TYPE_OBJECT) + { + for (rfont = MPLIST_VAL (frame->realized_font_list); rfont; + rfont = rfont->next) + if (rfont->font == font && rfont->driver == &mfont__ft_driver) + break; + if (! rfont) + { +#ifdef HAVE_FONTCONFIG + MFontFT *ft_info = (MFontFT *) font; + + if (! ft_info->charset) + { + FcPattern *pat = FcPatternBuild (NULL, FC_FILE, FcTypeString, + MSYMBOL_NAME (font->file), + NULL); + FcObjectSet *os = FcObjectSetBuild (FC_CHARSET, NULL); + FcFontSet *fs = FcFontList (fc_config, pat, os); + + if (fs->nfont > 0 + && FcPatternGetCharSet (fs->fonts[0], FC_CHARSET, 0, + &ft_info->charset) == FcResultMatch) + ft_info->charset = FcCharSetCopy (ft_info->charset); + else + ft_info->charset = FcCharSetCreate (); + FcFontSetDestroy (fs); + FcObjectSetDestroy (os); + FcPatternDestroy (pat); + } + return (FcCharSetHasChar (ft_info->charset, (FcChar32) c) == FcTrue); +#else /* not HAVE_FONTCONFIG */ + rfont = ft_open (frame, font, spec, NULL); +#endif /* not HAVE_FONTCONFIG */ + } + } + else + MFATAL (MERROR_FONT_FT); + + if (! rfont) + return 0; + ft_rfont = rfont->info; + idx = FT_Get_Char_Index (ft_rfont->ft_face, (FT_ULong) code); + return (idx != 0); +} + +/* The FreeType font driver function ENCODE_CHAR. */ + +static unsigned +ft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code) +{ + MRealizedFont *rfont; + MRealizedFontFT *ft_rfont; + FT_UInt idx; + + if (font->type == MFONT_TYPE_REALIZED) + rfont = (MRealizedFont *) font; + else if (font->type == MFONT_TYPE_OBJECT) + { + for (rfont = MPLIST_VAL (frame->realized_font_list); rfont; + rfont = rfont->next) + if (rfont->font == font && rfont->driver == &mfont__ft_driver) + break; + if (! rfont) + { + rfont = ft_open (frame, font, spec, NULL); + if (! rfont) + return -1; + } + } + else + MFATAL (MERROR_FONT_FT); + + ft_rfont = rfont->info; + idx = FT_Get_Char_Index (ft_rfont->ft_face, (FT_ULong) code); + return (idx ? (unsigned) idx : MCHAR_INVALID_CODE); +} + +/* The FreeType font driver function RENDER. */ + +#define NUM_POINTS 0x1000 + +typedef struct { + MDrawPoint points[NUM_POINTS]; + MDrawPoint *p; +} MPointTable; + +static void +ft_render (MDrawWindow win, int x, int y, + MGlyphString *gstring, MGlyph *from, MGlyph *to, + int reverse, MDrawRegion region) +{ + FT_Face ft_face; + MRealizedFace *rface = from->rface; + MFrame *frame = rface->frame; + FT_Int32 load_flags = FT_LOAD_RENDER; + MGlyph *g; + int i, j; + MPointTable point_table[8]; + int baseline_offset; + int pixel_mode = -1; + + if (from == to) + return; + + /* It is assured that the all glyphs in the current range use the + same realized face. */ + ft_face = rface->rfont->fontp; + baseline_offset = rface->rfont->baseline_offset >> 6; + + if (! gstring->anti_alias) + { +#ifdef FT_LOAD_TARGET_MONO + load_flags |= FT_LOAD_TARGET_MONO; +#else + load_flags |= FT_LOAD_MONOCHROME; +#endif + } + + for (i = 0; i < 8; i++) + point_table[i].p = point_table[i].points; + + for (g = from; g < to; x += g++->g.xadv) + { + unsigned char *bmp; + int intensity; + MPointTable *ptable; + int xoff, yoff; + int width, pitch; + + FT_Load_Glyph (ft_face, (FT_UInt) g->g.code, load_flags); + if (pixel_mode < 0) + pixel_mode = ft_face->glyph->bitmap.pixel_mode; + yoff = y - ft_face->glyph->bitmap_top + g->g.yoff; + bmp = ft_face->glyph->bitmap.buffer; + width = ft_face->glyph->bitmap.width; + pitch = ft_face->glyph->bitmap.pitch; + + if (pixel_mode != FT_PIXEL_MODE_MONO) + for (i = 0; i < ft_face->glyph->bitmap.rows; + i++, bmp += ft_face->glyph->bitmap.pitch, yoff++) + { + xoff = x + ft_face->glyph->bitmap_left + g->g.xoff; + for (j = 0; j < width; j++, xoff++) + { + intensity = bmp[j] >> 5; + if (intensity) + { + ptable = point_table + intensity; + ptable->p->x = xoff; + ptable->p->y = yoff - baseline_offset; + ptable->p++; + if (ptable->p - ptable->points == NUM_POINTS) + { + (*frame->driver->draw_points) + (frame, win, rface, + reverse ? 7 - intensity : intensity, + ptable->points, NUM_POINTS, region); + ptable->p = ptable->points; + } + } + } + } + else + for (i = 0; i < ft_face->glyph->bitmap.rows; + i++, bmp += ft_face->glyph->bitmap.pitch, yoff++) + { + xoff = x + ft_face->glyph->bitmap_left + g->g.xoff; + for (j = 0; j < width; j++, xoff++) + { + intensity = bmp[j / 8] & (1 << (7 - (j % 8))); + if (intensity) + { + ptable = point_table; + ptable->p->x = xoff; + ptable->p->y = yoff - baseline_offset; + ptable->p++; + if (ptable->p - ptable->points == NUM_POINTS) + { + (*frame->driver->draw_points) (frame, win, rface, + reverse ? 0 : 7, + ptable->points, NUM_POINTS, region); + ptable->p = ptable->points; + } + } + } + } + } + + if (pixel_mode != FT_PIXEL_MODE_MONO) + { + for (i = 1; i < 8; i++) + if (point_table[i].p != point_table[i].points) + (*frame->driver->draw_points) (frame, win, rface, reverse ? 7 - i : i, + point_table[i].points, + point_table[i].p - point_table[i].points, region); + } + else + { + if (point_table[0].p != point_table[0].points) + (*frame->driver->draw_points) (frame, win, rface, reverse ? 0 : 7, + point_table[0].points, + point_table[0].p - point_table[0].points, region); + } +} + +static int +ft_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum) +{ + MPlist *pl = NULL, *p; + int num = 0; + MPlist *file_list = NULL; + MPlist *family_list = NULL, *capability_list = NULL; + MSymbol registry = Mnil; + + MDEBUG_DUMP (" [FONT-FT] listing ", "", mdebug_dump_font (font)); + + if (font) + { + MSymbol family; + + registry = FONT_PROPERTY (font, MFONT_REGISTRY); + if (registry != Mnil && registry != Miso8859_1) + { + char *reg = MSYMBOL_NAME (registry); + + if (strncmp (reg, "unicode-", 8) + && strncmp (reg, "apple-roman", 11) + && (reg[0] < '0' || reg[0] > '9' || reg[1] != '-')) + goto done; + } + + if (font->file != Mnil + && ! (file_list = ft_list_file (font->file))) + goto done; + family = FONT_PROPERTY (font, MFONT_FAMILY); + if (family != Mnil + && (family_list = MPLIST_PLIST (ft_list_family (family, 1, 1))) + && MPLIST_TAIL_P (family_list)) + goto done; + if (font->capability != Mnil) + { + capability_list = ft_list_capability (font->capability); + if (! capability_list || MPLIST_TAIL_P (capability_list)) + goto done; + } + } + + if (! file_list && ! family_list && ! capability_list) + { + /* No restriction. Get all fonts. */ + pl = mplist (); + MPLIST_DO (family_list, ft_list_family (Mnil, 0, 1)) + { + MPLIST_DO (p, MPLIST_PLIST (family_list)) + mplist_push (pl, MPLIST_KEY (p), MPLIST_VAL (p)); + } + } + else + { + if (file_list) + { + pl = mplist (); + mplist_push (pl, MPLIST_KEY (file_list), MPLIST_VAL (file_list)); + } + if (family_list) + { + if (pl) + for (p = pl; ! MPLIST_TAIL_P (p);) + { + if (mplist_find_by_value (family_list, MPLIST_VAL (p))) + p = MPLIST_NEXT (p); + else + mplist_pop (p); + } + else + { + pl = mplist (); + MPLIST_DO (p, family_list) + mplist_push (pl, MPLIST_KEY (p), MPLIST_VAL (p)); + } + } + if (capability_list) + { + if (pl) + for (p = pl; ! MPLIST_TAIL_P (p);) + { + if (mplist_find_by_value (capability_list, MPLIST_VAL (p))) + p = MPLIST_NEXT (p); + else + mplist_pop (p); + } + else + { + pl = mplist (); + MPLIST_DO (p, capability_list) + mplist_push (pl, MPLIST_KEY (p), MPLIST_VAL (p)); + } + } + } + + if (font + && (font->property[MFONT_WEIGHT] + font->property[MFONT_STYLE] + + font->property[MFONT_STRETCH] + font->size) > 0) + { + MSymbol weight = FONT_PROPERTY (font, MFONT_WEIGHT); + MSymbol style = FONT_PROPERTY (font, MFONT_STYLE); + MSymbol stretch = FONT_PROPERTY (font, MFONT_STRETCH); + int size = font->size; + + for (p = pl; ! MPLIST_TAIL_P (p); ) + { + MFontFT *ft_info = MPLIST_VAL (p); + + if ((weight != Mnil + && weight != FONT_PROPERTY (&ft_info->font, MFONT_WEIGHT)) + || (style != Mnil + && style != FONT_PROPERTY (&ft_info->font, MFONT_STYLE)) + || (stretch != Mnil + && stretch != FONT_PROPERTY (&ft_info->font, + MFONT_STRETCH)) + || (size > 0 + && ft_info->font.size > 0 + && ft_info->font.size != size)) + mplist_pop (p); + else + p = MPLIST_NEXT (p); + } + } + + MPLIST_DO (p, pl) + { + mplist_push (plist, MPLIST_KEY (p), MPLIST_VAL (p)); + num++; + if (maxnum && maxnum <= num) + break; + } + M17N_OBJECT_UNREF (pl); + + done: + MDEBUG_PRINT1 (" %d found\n", num); + return num; +} + +static void +ft_list_family_names (MFrame *frame, MPlist *plist) +{ + MPlist *pl; + + if (! ft_font_list) + { +#ifdef HAVE_FONTCONFIG + fc_init_font_list (); +#else /* not HAVE_FONTCONFIG */ + ft_init_font_list (); +#endif /* not HAVE_FONTCONFIG */ + } + + MPLIST_DO (pl, ft_font_list) + { + MSymbol family = MPLIST_KEY (pl); + MPlist *p; + +#ifdef HAVE_FONTCONFIG + if (msymbol_get (family, Mgeneric_family) != Mnil) + continue; +#endif /* HAVE_FONTCONFIG */ + MPLIST_DO (p, plist) + { + MSymbol sym = MPLIST_SYMBOL (p); + + if (sym == family) + break; + if (strcmp (MSYMBOL_NAME (sym), MSYMBOL_NAME (family)) > 0) + { + mplist_push (p, Msymbol, family); + break; + } + } + if (MPLIST_TAIL_P (p)) + mplist_push (p, Msymbol, family); + } +} + +static int +ft_check_capability (MRealizedFont *rfont, MSymbol capability) +{ + MFontFT *ft_info = (MFontFT *) rfont->font; + MRealizedFontFT *ft_rfont = rfont->info; + MFontCapability *cap = mfont__get_capability (capability); + + if (cap->script_tag) + { + if (ft_check_cap_otf (ft_info, cap, ft_rfont->ft_face) < 0) + return -1; + } + else if (cap->script != Mnil + && ft_check_script (ft_info, cap->script, ft_rfont->ft_face) < 0) + return -1; + if (cap->language != Mnil + && ft_check_language (ft_info, cap->language, ft_rfont->ft_face) < 0) + return -1; + return 0; +} + +static MRealizedFont * +ft_encapsulate (MFrame *frame, MSymbol data_type, void *data) +{ + MFontFT *ft_info; + MRealizedFont *rfont; + MRealizedFontFT *ft_rfont; + FT_Face ft_face; + + if (data_type == Mfontconfig) + { +#ifdef HAVE_FONTCONFIG + FcPattern *pattern = data; + + if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &ft_face) + != FcResultMatch) + return NULL; + ft_info = fc_gen_font (pattern, NULL); +#else /* not HAVE_FONTCONFIG */ + return NULL; +#endif /* not HAVE_FONTCONFIG */ + } + else if (data_type == Mfreetype) + { + ft_face = data; + ft_info = ft_gen_font (ft_face); + } + else + return NULL; + + M17N_OBJECT (ft_rfont, free_ft_rfont, MERROR_FONT_FT); + ft_rfont->ft_face = ft_face; + ft_rfont->face_encapsulated = 1; + + MDEBUG_PRINT1 (" [FONT-FT] encapsulating %s", (char *) ft_face->family_name); + + MSTRUCT_CALLOC (rfont, MERROR_FONT_FT); + rfont->id = ft_info->font.file; + rfont->font = (MFont *) ft_info; + rfont->info = ft_rfont; + rfont->fontp = ft_face; + rfont->driver = &mfont__ft_driver; + rfont->spec = ft_info->font; + rfont->spec.type = MFONT_TYPE_REALIZED; + rfont->frame = frame; + rfont->ascent = ft_face->size->metrics.ascender >> 6; + rfont->descent = - ft_face->size->metrics.descender >> 6; + rfont->max_advance = ft_face->size->metrics.max_advance >> 6; + rfont->baseline_offset = 0; + rfont->x_ppem = ft_face->size->metrics.x_ppem; + rfont->y_ppem = ft_face->size->metrics.y_ppem; +#ifdef HAVE_FTBDF_H + { + BDF_PropertyRec prop; + + if (! FT_IS_SCALABLE (ft_face) + && FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &prop) == 0) + { + rfont->baseline_offset = prop.u.integer << 6; + rfont->ascent += prop.u.integer << 6; + rfont->descent -= prop.u.integer << 6; + } + } +#endif /* HAVE_FTBDF_H */ + if (FT_IS_SCALABLE (ft_face)) + rfont->average_width = 0; + else + rfont->average_width = ft_face->available_sizes->width << 6; + rfont->next = MPLIST_VAL (frame->realized_font_list); + MPLIST_VAL (frame->realized_font_list) = rfont; + + return rfont; +} + +static void +ft_close (MRealizedFont *rfont) +{ + if (! rfont->encapsulating) + return; + free (rfont->font); + M17N_OBJECT_UNREF (rfont->info); + free (rfont); +} + +/* See the comment of parse_otf_command (m17n-flt.c). */ + +static int +ft_check_otf (MFLTFont *font, MFLTOtfSpec *spec) +{ +#define FEATURE_NONE(IDX) (! spec->features[IDX]) + +#define FEATURE_ANY(IDX) \ + (spec->features[IDX] \ + && spec->features[IDX][0] == 0xFFFFFFFF && spec->features[IDX][1] == 0) + +#ifdef HAVE_OTF + OTF_Tag *tags; + int i, n, negative; + OTF *otf = get_otf (font, NULL); + + if (FEATURE_ANY (0) && FEATURE_ANY (1)) + /* Return 1 iff any of GSUB or GPOS support the script (and language). */ + return (otf + && (OTF_check_features (otf, 0, spec->script, spec->langsys, + NULL, 0) > 0 + || OTF_check_features (otf, 1, spec->script, spec->langsys, + NULL, 0) > 0)); + + for (i = 0; i < 2; i++) + if (! FEATURE_ANY (i)) + { + if (FEATURE_NONE (i)) + { + if (otf + && OTF_check_features (otf, i == 0, spec->script, spec->langsys, + NULL, 0) > 0) + return 0; + continue; + } + if (spec->features[i][0] == 0xFFFFFFFF) + { + if (! otf + || OTF_check_features (otf, i == 0, spec->script, spec->langsys, + NULL, 0) <= 0) + continue; + } + else if (! otf) + return 0; + for (n = 1; spec->features[i][n]; n++); + tags = alloca (sizeof (OTF_Tag) * n); + for (n = 0, negative = 0; spec->features[i][n]; n++) + { + if (spec->features[i][n] == 0xFFFFFFFF) + negative = 1; + else if (negative) + tags[n - 1] = spec->features[i][n] | 0x80000000; + else + tags[n] = spec->features[i][n]; + } + if (OTF_check_features (otf, i == 0, spec->script, spec->langsys, + tags, n - negative) != 1) + return 0; + } + return 1; + +#endif /* HAVE_OTF */ + return (FEATURE_NONE (0) ? (FEATURE_NONE (1) || FEATURE_ANY (1)) + : (FEATURE_NONE (1) && FEATURE_ANY (0))); +} + +#ifdef HAVE_OTF + +static OTF * +get_otf (MFLTFont *font, FT_Face *ft_face) +{ + MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont; + MFontFT *ft_info = (MFontFT *) rfont->font; + MRealizedFontFT *ft_rfont = rfont->info; + OTF *otf = ft_info->otf; + + if (! otf) + { +#if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4) + otf = OTF_open_ft_face (ft_rfont->ft_face); +#else + otf = OTF_open (MSYMBOL_NAME (ft_info->font.file)); +#endif + if (! otf || OTF_get_table (otf, "head") < 0) + otf = invalid_otf; + ft_info->otf = otf; + } + if (ft_face) + *ft_face = ft_rfont->ft_face; + return (otf == invalid_otf ? NULL : otf); +} + +#define DEVICE_DELTA(table, size) \ + (((size) >= (table).StartSize && (size) <= (table).EndSize) \ + ? (table).DeltaValue[(size) - (table).StartSize] << 6 \ + : 0) + +void +adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face, + unsigned code, int x_ppem, int y_ppem, int *x, int *y) +{ + if (anchor->AnchorFormat == 2) + { + FT_Outline *outline; + int ap = anchor->f.f1.AnchorPoint; + + FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME); + outline = &ft_face->glyph->outline; + if (ap < outline->n_points) + { + *x = outline->points[ap].x << 6; + *y = outline->points[ap].y << 6; + } + } + else if (anchor->AnchorFormat == 3) + { + if (anchor->f.f2.XDeviceTable.offset) + *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, x_ppem); + if (anchor->f.f2.YDeviceTable.offset) + *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, y_ppem); + } +} +#endif /* HAVE_OTF */ + +#ifdef HAVE_OTF + +static int +ft_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, + MFLTGlyphString *in, int from, int to, + MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment) +{ + int len = to - from; + int i, j, gidx; + MGlyph *in_glyphs = (MGlyph *) (in->glyphs); + MGlyph *out_glyphs = out ? (MGlyph *) (out->glyphs) : NULL; + OTF *otf; + FT_Face face; + OTF_GlyphString otf_gstring; + OTF_Glyph *otfg; + char script[5], *langsys = NULL; + char *gsub_features = NULL, *gpos_features = NULL; + unsigned int tag; + + if (len == 0) + return from; + otf = get_otf (font, &face); + if (! otf) + goto simple_copy; + OTF_tag_name (spec->script, script); + if (spec->langsys) + { + langsys = alloca (5); + OTF_tag_name (spec->langsys, langsys); + } + for (i = 0; i < 2; i++) + { + char *p; + + if (spec->features[i]) + { + for (j = 0; spec->features[i][j]; j++); + if (i == 0) + p = gsub_features = alloca (6 * j); + else + p = gpos_features = alloca (6 * j); + for (j = 0; spec->features[i][j]; j++) + { + if (spec->features[i][j] == 0xFFFFFFFF) + *p++ = '*', *p++ = ','; + else + { + OTF_tag_name (spec->features[i][j], p); + p[4] = ','; + p += 5; + } + } + *--p = '\0'; + } + } + + /* Extra room from pseudo glyphs. OTF_drive_features () may need + more rooms. In that case, otf_gstring.glyphs is reallocated. */ + otf_gstring.size = len * 2; + if (! MTABLE_CALLOC_SAFE (otf_gstring.glyphs, otf_gstring.size)) + MERROR (MERROR_MEMORY, -1); + for (i = 0; i < len; i++) + { + otf_gstring.glyphs[i].c = ((MGlyph *)in->glyphs)[from + i].g.c & 0x11FFFF; + otf_gstring.glyphs[i].glyph_id = ((MGlyph *)in->glyphs)[from + i].g.code; + otf_gstring.glyphs[i].positioning_type = ((MGlyph *)in->glyphs)[from + i].libotf_positioning_type; + } + otf_gstring.used = len; + + OTF_drive_gdef (otf, &otf_gstring); + gidx = out ? out->used : from; + + if (gsub_features) + { + OTF_Feature *features; + MGlyph *g; + +#ifdef OTF_POSITIONING_TYPE_GET_FORMAT + if (OTF_drive_gsub_features (otf, &otf_gstring, script, langsys, + gsub_features) < 0) + goto simple_copy; +#else + if (OTF_drive_gsub_with_log (otf, &otf_gstring, script, langsys, + gsub_features) < 0) + goto simple_copy; +#endif + features = otf->gsub->FeatureList.Feature; + if (out) + { + if (out->allocated < gidx + otf_gstring.used) + return -2; + for (i = 0, otfg = otf_gstring.glyphs, g = out_glyphs + gidx; + i < otf_gstring.used; i++, otfg++, g++, out->used++) + { + int j; + int min_from, max_to; + int feature_idx; + +#ifdef OTF_POSITIONING_TYPE_GET_FORMAT + feature_idx = OTF_POSITIONING_TYPE_GET_FEATURE (otfg); +#else + feature_idx = otfg->positioning_type >> 4; +#endif + + *g = in_glyphs[from + otfg->f.index.from]; + min_from = g->g.from, max_to = g->g.to; + g->g.c = 0; + for (j = otfg->f.index.from; j <= otfg->f.index.to; j++) + if (in_glyphs[from + j].g.code == otfg->glyph_id) + { + g->g.c = in_glyphs[from + j].g.c; + break; + } + if (feature_idx) + { + tag = features[feature_idx - 1].FeatureTag; + tag = PACK_OTF_TAG (tag); + g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag; + } + for (j = otfg->f.index.from + 1; j <= otfg->f.index.to; j++) + { + if (min_from > in_glyphs[from + j].g.from) + min_from = in_glyphs[from + j].g.from; + if (max_to < in_glyphs[from + j].g.to) + max_to = in_glyphs[from + j].g.to; + } + if (g->g.code != otfg->glyph_id) + { + g->g.code = otfg->glyph_id; + g->g.measured = 0; + } + g->g.from = min_from, g->g.to = max_to; + } + } + else + { + for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; + i++, otfg++) + { + int feature_idx; + +#ifdef OTF_POSITIONING_TYPE_GET_FORMAT + feature_idx = OTF_POSITIONING_TYPE_GET_FEATURE (otfg); +#else + feature_idx = otfg->positioning_type >> 4; +#endif + if (feature_idx) + { + tag = features[feature_idx - 1].FeatureTag; + tag = PACK_OTF_TAG (tag); + for (j = otfg->f.index.from; j <= otfg->f.index.to; j++) + { + g = in_glyphs + (from + j); + g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag; + } + } + } + } + } + else if (out) + { + if (out->allocated < gidx + len) + return -2; + for (i = 0; i < len; i++) + out_glyphs[out->used++] = in_glyphs[from + i]; + } + + if (gpos_features) + { + OTF_Feature *features; + MGlyph *g; + +#ifdef OTF_POSITIONING_TYPE_GET_FORMAT + if (OTF_drive_gpos_features (otf, &otf_gstring, script, langsys, + gpos_features) < 0) + return to; +#else + if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys, + gpos_features) < 0) + return to; +#endif + features = otf->gpos->FeatureList.Feature; + if (out) + { + MGlyph *base = NULL, *mark = NULL; + int x_ppem = face->size->metrics.x_ppem; + int y_ppem = face->size->metrics.y_ppem; + int x_scale = face->size->metrics.x_scale; + int y_scale = face->size->metrics.y_scale; + + for (i = j = 0, otfg = otf_gstring.glyphs, g = out_glyphs + gidx; + i < otf_gstring.used; i++, otfg++) + { + MGlyph *prev; + int adjust_idx = otfg->glyph_id ? j : j - 1; + int positioning_type, feature_idx; + +#ifdef OTF_POSITIONING_TYPE_GET_FORMAT + positioning_type = OTF_POSITIONING_TYPE_GET_FORMAT (otfg); + feature_idx = OTF_POSITIONING_TYPE_GET_FEATURE (otfg); +#else + positioning_type = otfg->positioning_type & 0xF; + feature_idx = otfg->positioning_type >> 4; +#endif + + if (feature_idx) + { + tag = features[feature_idx - 1].FeatureTag; + tag = PACK_OTF_TAG (tag); + g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag; + } + + switch (positioning_type) + { + case 0: + break; + case 1: /* Single */ + case 2: /* Pair */ + { + int format = otfg->f.f1.format; + + if (format & OTF_XPlacement) + adjustment[adjust_idx].xoff + += otfg->f.f1.value->XPlacement * x_scale / 0x10000; + if (format & OTF_XPlaDevice) + adjustment[adjust_idx].xoff + += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem); + if (format & OTF_YPlacement) + adjustment[adjust_idx].yoff + -= otfg->f.f1.value->YPlacement * y_scale / 0x10000; + if (format & OTF_YPlaDevice) + adjustment[adjust_idx].yoff + -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem); + if (format & OTF_XAdvance) + adjustment[adjust_idx].xadv + += otfg->f.f1.value->XAdvance * x_scale / 0x10000; + if (format & OTF_XAdvDevice) + adjustment[adjust_idx].xadv + += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem); + if (format & OTF_YAdvance) + adjustment[adjust_idx].yadv + += otfg->f.f1.value->YAdvance * y_scale / 0x10000; + if (format & OTF_YAdvDevice) + adjustment[adjust_idx].yadv + += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem); + adjustment[adjust_idx].set = 1; + } + break; + case 3: /* Cursive */ + /* Not yet supported. */ + break; + case 4: /* Mark-to-Base */ + case 5: /* Mark-to-Ligature */ + if (! base) + break; + prev = base; + goto label_adjust_anchor; + default: /* i.e. case 6 Mark-to-Mark */ + if (! mark) + break; + prev = mark; +#ifdef OTF_POSITIONING_TYPE_GET_FORMAT + { + int distance = OTF_POSITIONING_TYPE_GET_MARKDISTANCE (otfg); + + if (distance > 0) + { + prev = g - distance; + if (prev < out_glyphs) + prev = mark; + } + } +#endif + label_adjust_anchor: + { + int base_x, base_y, mark_x, mark_y; + int this_from, this_to; + int k; + + base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000; + base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000; + mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000; + mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;; + + if (otfg->f.f4.base_anchor->AnchorFormat != 1) + adjust_anchor (otfg->f.f4.base_anchor, face, prev->g.code, + x_ppem, y_ppem, &base_x, &base_y); + if (otfg->f.f4.mark_anchor->AnchorFormat != 1) + adjust_anchor (otfg->f.f4.mark_anchor, face, g->g.code, + x_ppem, y_ppem, &mark_x, &mark_y); + adjustment[adjust_idx].xoff = base_x - mark_x; + adjustment[adjust_idx].yoff = - (base_y - mark_y); + adjustment[adjust_idx].back = (g - prev); + adjustment[adjust_idx].xadv = 0; + adjustment[adjust_idx].advance_is_absolute = 1; + adjustment[adjust_idx].set = 1; + this_from = g->g.from; + this_to = g->g.to; + for (k = 0; prev + k < g; k++) + { + if (this_from > prev[k].g.from) + this_from = prev[k].g.from; + if (this_to < prev[k].g.to) + this_to = prev[k].g.to; + } + for (; prev <= g; prev++) + { + prev->g.from = this_from; + prev->g.to = this_to; + } + } + } + if (otfg->glyph_id) + { + if (otfg->GlyphClass == OTF_GlyphClass0) + base = mark = g; + else if (otfg->GlyphClass == OTF_GlyphClassMark) + mark = g; + else + base = g; + j++, g++; + } + } + } + else + { + for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; + i++, otfg++) + if (otfg->positioning_type & 0xF) + { + int feature_idx; + +#ifdef OTF_POSITIONING_TYPE_GET_FORMAT + feature_idx = OTF_POSITIONING_TYPE_GET_FEATURE (otfg); +#else + feature_idx = otfg->positioning_type >> 4; +#endif + if (feature_idx) + { + tag = features[feature_idx - 1].FeatureTag; + tag = PACK_OTF_TAG (tag); + for (j = otfg->f.index.from; j <= otfg->f.index.to; j++) + { + g = in_glyphs + (from + j); + g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag; + } + } + } + } + } + + free (otf_gstring.glyphs); + return to; + + simple_copy: + if (otf_gstring.glyphs) + free (otf_gstring.glyphs); + if (out) + { + if (out->allocated < out->used + len) + return -2; + font->get_metrics (font, in, from, to); + memcpy ((MGlyph *)out->glyphs + out->used, (MGlyph *) in->glyphs + from, + sizeof (MGlyph) * len); + out->used += len; + } + return to; +} + +#else /* not HAVE_OTF */ + +static int +ft_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, + MFLTGlyphString *in, int from, int to, + MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment) +{ + int len = to - from; + if (out) + { + if (out->allocated < out->used + len) + return -2; + font->get_metrics (font, in, from, to); + memcpy ((MGlyph *)out->glyphs + out->used, (MGlyph *) in->glyphs + from, + sizeof (MGlyph) * len); + out->used += len; + } + return to; +} + +#endif /* not HAVE_OTF */ + + +static int +ft_try_otf (MFLTFont *font, MFLTOtfSpec *spec, + MFLTGlyphString *in, int from, int to) +{ + return ft_drive_otf (font, spec, in, from, to, NULL, NULL); +} + + +#ifdef HAVE_OTF +static unsigned char *iterate_bitmap; + +static int +iterate_callback (OTF *otf, const char *feature, unsigned glyph_id) +{ + if (glyph_id <= otf->cmap->max_glyph_id) + iterate_bitmap[glyph_id / 8] |= 1 << (glyph_id % 8); + return 0; +} + +static int +ft_iterate_otf_feature (MFLTFont *font, MFLTOtfSpec *spec, + int from, int to, unsigned char *table) +{ + OTF *otf = get_otf (font, NULL); + char id[13]; + int bmp_size; + unsigned char *bitmap = NULL; + int i, j; + char script[5], *langsys = NULL; + + if (! otf) + return -1; + if (OTF_get_table (otf, "cmap") < 0) + return -1; + if (! spec->features[0]) + return -1; + strcpy (id, "feature-"); + id[12] = '\0'; + OTF_tag_name (spec->script, script); + if (spec->langsys) + { + langsys = alloca (5); + OTF_tag_name (spec->langsys, langsys); + } + bmp_size = (otf->cmap->max_glyph_id / 8) + 1; + for (i = 0; spec->features[0][i]; i++) + { + unsigned char *bmp; + + OTF_tag_name (spec->features[0][i], id + 8); + bmp = OTF_get_data (otf, id); + if (! bmp) + { + iterate_bitmap = bmp = calloc (bmp_size, 1); + OTF_iterate_gsub_feature (otf, iterate_callback, + script, langsys, id + 8); + OTF_put_data (otf, id, bmp, free); + } + if (i == 0 && ! spec->features[0][1]) + /* Single feature */ + bitmap = bmp; + else + { + if (! bitmap) + { + bitmap = alloca (bmp_size); + memcpy (bitmap, bmp, bmp_size); + } + else + { + int j; + + for (j = 0; j < bmp_size; j++) + bitmap[j] &= bmp[j]; + } + } + } + for (i = 0; i < bmp_size; i++) + if (bitmap[i]) + { + for (j = 0; j < 8; j++) + if (bitmap[i] & (1 << j)) + { + int c = OTF_get_unicode (otf, (i * 8) + j); + + if (c >= from && c <= to) + table[c - from] = 1; + } + } + return 0; +} +#endif + + + +/* Internal API */ + +MFontDriver mfont__ft_driver = + { ft_select, ft_open, ft_find_metric, ft_has_char, ft_encode_char, + ft_render, ft_list, ft_list_family_names, ft_check_capability, + ft_encapsulate, ft_close, ft_check_otf, ft_drive_otf, ft_try_otf, +#ifdef HAVE_OTF + ft_iterate_otf_feature +#endif /* HAVE_OTF */ + }; + +int +mfont__ft_init () +{ + int i; + + if (FT_Init_FreeType (&ft_library) != 0) + MERROR (MERROR_FONT_FT, -1); + + for (i = 0; i < ft_to_prop_size; i++) + ft_to_prop[i].len = strlen (ft_to_prop[i].ft_style); + + Mmedium = msymbol ("medium"); + Mr = msymbol ("r"); + Mnull = msymbol (""); + + M0[0] = msymbol ("0-0"); + M0[1] = msymbol ("0-1"); + M0[2] = msymbol ("0-2"); + M0[3] = msymbol ("0-3"); + M0[4] = msymbol ("0-4"); + M3_1 = msymbol ("3-1"); + M1_0 = msymbol ("1-0"); + +#ifdef HAVE_FONTCONFIG + for (i = 0; i < (sizeof (fc_all_table) / sizeof fc_all_table[0]); i++) + { + FC_vs_M17N_font_prop *table = fc_all_table[i]; + int j; + + for (j = 0; table[j].m17n_value; j++) + table[j].sym = msymbol (table[j].m17n_value); + table[j].sym = table[j - 1].sym; + } + + { + char *pathname; + struct stat buf; + MPlist *plist; + MSymbol serif, sans_serif, monospace; + + fc_config = FcInitLoadConfigAndFonts (); + if (mfont_freetype_path) + { + MPLIST_DO (plist, mfont_freetype_path) + if (MPLIST_STRING_P (plist) + && (pathname = MPLIST_STRING (plist)) + && stat (pathname, &buf) == 0) + { + FcStrList *strlist = FcConfigGetFontDirs (fc_config); + FcChar8 *dir; + + while ((dir = FcStrListNext (strlist))) + if (strcmp ((char *) dir, pathname) == 0) + break; + if (! dir) + FcConfigAppFontAddDir (fc_config, (FcChar8 *) pathname); + FcStrListDone (strlist); + } + } + Mgeneric_family = msymbol ("generic famly"); + serif = msymbol ("serif"); + msymbol_put (serif, Mgeneric_family, serif); + sans_serif = msymbol ("sans-serif"); + msymbol_put (sans_serif, Mgeneric_family, sans_serif); + msymbol_put (msymbol ("sans serif"), Mgeneric_family, sans_serif); + msymbol_put (msymbol ("sans"), Mgeneric_family, sans_serif); + monospace = msymbol ("monospace"); + msymbol_put (monospace, Mgeneric_family, monospace); + msymbol_put (msymbol ("mono"), Mgeneric_family, monospace); + } +#endif /* HAVE_FONTCONFIG */ + + return 0; +} + +void +mfont__ft_fini () +{ + MPlist *plist, *p; + + if (ft_default_list) + { + M17N_OBJECT_UNREF (ft_default_list); + ft_default_list = NULL; + } + + if (ft_font_list) + { + MPLIST_DO (plist, ft_font_list) + { + if (MPLIST_VAL (plist)) + MPLIST_DO (p, MPLIST_VAL (plist)) + { + if (MPLIST_KEY (p) != Mt) + free_ft_info (MPLIST_VAL (p)); + } + M17N_OBJECT_UNREF (MPLIST_VAL (plist)); + } + M17N_OBJECT_UNREF (ft_font_list); + ft_font_list = NULL; + + if (ft_language_list) + { + MPLIST_DO (plist, ft_language_list) + M17N_OBJECT_UNREF (MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (ft_language_list); + ft_language_list = NULL; + } + + if (ft_script_list) + { + MPLIST_DO (plist, ft_script_list) + M17N_OBJECT_UNREF (MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (ft_script_list); + ft_script_list = NULL; + } + + if (ft_capability_list) + { + MPLIST_DO (plist, ft_capability_list) + M17N_OBJECT_UNREF (MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (ft_capability_list); + ft_capability_list = NULL; + } + + if (ft_file_list) + { + MPLIST_DO (plist, ft_file_list) + M17N_OBJECT_UNREF (MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (ft_file_list); + ft_file_list = NULL; + } + } + FT_Done_FreeType (ft_library); +#ifdef HAVE_FONTCONFIG + FcConfigDestroy (fc_config); + fc_config = NULL; +#endif /* HAVE_FONTCONFIG */ + all_fonts_scaned = 0; +} + +#ifdef HAVE_FONTCONFIG + +int +mfont__ft_parse_name (const char *name, MFont *font) +{ + FcPattern *pat = FcNameParse ((FcChar8 *) name); + FcChar8 *str; + int val; + double size; + char *buf; + int bufsize = 0; + + if (! pat) + return -1; + if (FcPatternGetString (pat, FC_FOUNDRY, 0, &str) == FcResultMatch) + { + STRDUP_LOWER (buf, bufsize, (char *) str); + mfont__set_property (font, MFONT_FOUNDRY, msymbol (buf)); + } + if (FcPatternGetString (pat, FC_FAMILY, 0, &str) == FcResultMatch) + { + STRDUP_LOWER (buf, bufsize, (char *) str); + mfont__set_property (font, MFONT_FAMILY, msymbol (buf)); + } + if (FcPatternGetInteger (pat, FC_WEIGHT, 0, &val) == FcResultMatch) + mfont__set_property (font, MFONT_WEIGHT, + fc_decode_prop (val, fc_weight_table, + fc_weight_table_size)); + if (FcPatternGetInteger (pat, FC_SLANT, 0, &val) == FcResultMatch) + mfont__set_property (font, MFONT_STYLE, + fc_decode_prop (val, fc_slant_table, + fc_slant_table_size)); + if (FcPatternGetInteger (pat, FC_WIDTH, 0, &val) == FcResultMatch) + mfont__set_property (font, MFONT_STRETCH, + fc_decode_prop (val, fc_width_table, + fc_width_table_size)); + if (FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &size) == FcResultMatch) + font->size = size * 10 + 0.5; + else if (FcPatternGetDouble (pat, FC_SIZE, 0, &size) == FcResultMatch) + font->size = - (size * 10 + 0.5); + if (FcPatternGetString (pat, FC_FILE, 0, &str) == FcResultMatch) + { + font->file = msymbol ((char *) str); + } + mfont__set_property (font, MFONT_REGISTRY, Municode_bmp); + font->type = MFONT_TYPE_SPEC; + FcPatternDestroy (pat); + return 0; +} + +char * +mfont__ft_unparse_name (MFont *font) +{ + FcPattern *pat = fc_get_pattern (font); + char *name = (char *) FcNameUnparse (pat); + + FcPatternDestroy (pat); + return name; +} +#endif /* HAVE_FONTCONFIG */ + +#endif /* HAVE_FREETYPE */ diff --git a/src/font.c b/src/font.c new file mode 100644 index 0000000..823cac4 --- /dev/null +++ b/src/font.c @@ -0,0 +1,3239 @@ +/* font.c -- font module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nFont + @brief Font object. + + The m17n GUI API represents a font by an object of the type @c + MFont. A font can have @e font @e properties. Like other types + of properties, a font property consists of a key and a value. The + key of a font property must be one of the following symbols: + + @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, + @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing. + + When the key of a font property is @c Msize or @c Mresolution, its + value is an integer. Otherwise the value is a symbol. + + The notation "xxx property of F" means the font property that + belongs to font F and whose key is @c Mxxx. + + The value of a foundry property is a symbol representing font + foundry information, e.g. adobe, misc, etc. + + The value of a family property is a symbol representing font family + information, e.g. times, helvetica, etc. + + The value of a weight property is a symbol representing weight + information, e.g. normal, bold, etc. + + The value of a style property is a symbol representing slant + information, e.g. normal, italic, etc. + + The value of a stretch property is a symbol representing width + information, e.g. normal, semicondensed, etc. + + The value of an adstyle property is a symbol representing abstract + font family information, e.g. serif, sans-serif, etc. + + The value of a registry property is a symbol representing registry + information, e.g. iso10646-1, iso8895-1, etc. + + The value of a size property is an integer representing design + size in the unit of 1/10 point. + + The value of a resolution property is an integer representing + assumed device resolution in the unit of dots per inch (dpi). + + The value of a type property is a symbol indicating a font driver; + currently Mx or Mfreetype. + + The m17n library uses font objects for two purposes: to receive + font specification from an application program, and to present + available fonts to an application program. When the m17n library + presents an available font to an application program, all font + properties have a concrete value. + + The m17n library supports three kinds of fonts: Window system fonts, + FreeType fonts, and OpenType fonts. + +
    + +
  • Window system fonts + + The m17n-X library supports all fonts handled by an X server and + an X font server. The correspondence between XLFD fields and font + properties are shown below. + +@verbatim + XLFD field property + --------------- -------- + FOUNDRY foundry + FAMILY_NAME family + WEIGHT_NAME weight + SLANT style + SETWIDTH_NAME stretch + ADD_STYLE_NAME adstyle + PIXEL_SIZE size + RESOLUTION_Y resolution + CHARSET_REGISTRY-CHARSET_ENCODING registry +@endverbatim + + XLFD fields not listed in the above table are ignored. + +
  • FreeType fonts + + The m17n library, if configured to use the FreeType library, + supports all fonts that can be handled by the FreeType library. + The variable #mfont_freetype_path is initialized properly according + to the configuration of the m17n library and the environment + variable @c M17NDIR. See the documentation of the variable for + details. + + If the m17n library is configured to use the fontconfig library, + in addition to #mfont_freetype_path, all fonts available via + fontconfig are supported. + + The family name of a FreeType font corresponds to the family + property. Style names of FreeType fonts correspond to the weight, + style, and stretch properties as below. + +@verbatim + style name weight style stretch + ---------- ------ ----- ------- + Regular medium r normal + Italic medium i normal + Bold bold r normal + Bold Italic bold i normal + Narrow medium r condensed + Narrow Italic medium i condensed + Narrow Bold bold r condensed + Narrow Bold Italic bold i condensed + Black black r normal + Black Italic black i normal + Oblique medium o normal + BoldOblique bold o normal +@endverbatim + + Style names not listed in the above table are treated as + "Regular". + + Combination of a platform ID and an encoding ID corresponds to the + registry property. For example, if a font has the combination (1 + 1), the registry property is 1-1. Some frequent combinations have + a predefined registry property as below. + +@verbatim + platform ID encoding ID registry property + ----------- ----------- ----------------- + 0 3 unicode-bmp + 0 4 unicode-full + 1 0 apple-roman + 3 1 unicode-bmp + 3 1 unicode-full +@endverbatim + + Thus, a font that has two combinations (1 0) and (3 1) corresponds + to four font objects whose registries are 1-0, apple-roman, 3-1, + and unicode-bmp. + +
  • OpenType fonts + + The m17n library, if configured to use both the FreeType library + and the OTF library, supports any OpenType fonts. The list of + actually available fonts is created in the same way as in the case + of FreeType fonts. If a fontset instructs to use an OpenType font + via an FLT (Font Layout Table), and the FLT has an OTF-related + command (e.g. otf:deva), the OTF library converts a character + sequence to a glyph code sequence according to the OpenType layout + tables of the font, and the FreeType library gives a bitmap image + for each glyph. + +
+ + */ + +/***ja + @addtogroup m17nFont + @brief �ե���ȥ��֥�������. + + m17n GUI API �ϥե���Ȥ� @c MFont ���Υ��֥������ȤȤ���ɽ�����롣 + �ե���Ȥ� @e �ե���ȥץ��ѥƥ� ����Ĥ��Ȥ��Ǥ��롣¾�Υ����פΥ� + ���ѥƥ�Ʊ�͡��ե���ȥץ��ѥƥ��ϥ������ͤ���ʤꡢ�����ϰʲ��Υ� + ��ܥ�Τ����줫�Ǥ��롣 + + @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, + @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing + + �ե���ȥץ��ѥƥ��Υ����� @c Msize ���뤤�� @c Mresolution + �ξ�硢�ͤ������ͤǤ��ꡢ����������ʳ��ξ�硢�ͤϥ���ܥ�Ǥ��롣 + + �֥ե���� F �Υե���ȥץ��ѥƥ��Τ��������� @c Mxxx + �Ǥ����ΡפΤ��Ȥ��ñ�ˡ�F �� xxx �ץ��ѥƥ��פȸƤ֤��Ȥ����롣 + + foundry �ץ��ѥƥ����ͤϡ�adobe, misc + ���Υե���Ȥγ�ȯ������򼨤�����ܥ�Ǥ��롣 + + family �ץ��ѥƥ����ͤϡ�times, helvetica + ���Υե���ȥե��ߥ꡼�򼨤�����ܥ�Ǥ��롣 + + weight �ץ��ѥƥ����ͤϡ�normal, bold ���������˴ؤ������򼨤�����ܥ�Ǥ��롣 + + style �ץ��ѥƥ����ͤϡ�normal, italic + ���Υ�������˴ؤ������򼨤�����ܥ�Ǥ��롣 + + stretch �ץ��ѥƥ����ͤϡ�normal, semicondensed + ����ʸ�����˴ؤ������򼨤�����ܥ�Ǥ��롣 + + adstyle �ץ��ѥƥ����ͤϡ�serif, sans-serif + �������Ū�ʥե���ȥե��ߥ꡼�˴ؤ������򼨤�����ܥ�Ǥ��롣 + + registry �ץ��ѥƥ����ͤϡ�iso10646, iso8895-1 + ���Υ쥸���ȥ����򼨤�����ܥ�Ǥ��롣 + + size �ץ��ѥƥ����ͤϡ��ե���ȤΥǥ����󥵥�����ɽ�魯�����ͤǤ��ꡢ + ñ�̤�1/10 �ݥ���ȤǤ��롣 + + resolution �ץ��ѥƥ����ͤϡ����ꤵ��Ƥ���ǥХ����β����٤�ɽ�魯 + �����ͤǤ��ꡢñ�̤�dots per inch (dpi) �Ǥ��롣 + + type �ץ��ѥƥ����ͤϡ��ե���ȥɥ饤�Ф�ؼ��������� Mx �⤷���� + Mfreetype �Ǥ��롣 + + m17n �饤�֥��ϥե���ȥ��֥������Ȥ򣲤Ĥ���Ū���Ѥ��Ƥ��롣���� + �ꥱ�������ץ�����फ��ե���Ȥλ������������Ū�ȡ����ץꥱ�� + �����ץ����������Ѳ�ǽ�ʥե���Ȥ��󼨤�����Ū�Ǥ��롣���ץꥱ�� + �����ץ��������Ф����󼨤�Ԥ��ݤˤϡ��ե���ȥץ��ѥƥ��Ϥ��� + �ƶ���Ū���ͤ���ġ� + + m17n �饤�֥��� Window �����ƥ�ե���ȡ�FreeType�ե���ȡ� + OpenType�ե���ȤΣ�����򥵥ݡ��Ȥ��Ƥ��롣 + +
    + +
  • Window �����ƥ�ե���� + + m17n X �饤�֥��ϡ�X �����Ф� X �ե���ȥ����Ф���갷�����ƤΥե���Ȥ򥵥ݡ��Ȥ��롣 + XLFD �γƥե�����ɤȥե���ȥץ��ѥƥ����б��ϰʲ����̤ꡣ����ɽ�ˤʤ��ե�����ɤ�̵�뤵��롣 + +@verbatim + XLFD �ե������ �ץ��ѥƥ� + --------------- -------- + FOUNDRY foundry + FAMILY_NAME family + WEIGHT_NAME weight + SLANT style + SETWIDTH_NAME stretch + ADD_STYLE_NAME adstyle + PIXEL_SIZE size + RESOLUTION_Y resolution + CHARSET_REGISTRY-CHARSET_ENCODING registry +@endverbatim + +
  • FreeType fonts + + m17n �饤�֥��ϡ�FreeType �饤�֥���Ȥ��褦�����ꤵ�줿���ˤϡ� + FreeType ���������٤ƤΥե���Ȥ򥵥ݡ��Ȥ��롣�ѿ� + #mfont_freetype_path �� m17n �饤�֥�������ȴĶ��ѿ� @c M17NDIR + �˱����ƽ��������롣�ܺ٤��ѿ��������򻲾ȤΤ��ȡ� + + �⤷ m17n �饤�֥�꤬ fontconfig �饤�֥���Ȥ��褦�����ꤵ�줿���ˤϡ� + #mfont_freetype_path �˲ä��ơ� fontconfig �ǻ��Ѳ�ǽ�ʥե���Ȥ⤹�٤ƥ��ݡ��Ȥ���롣 + + FreeType �ե���ȤΥե��ߥ�̾�� family �ץ��ѥƥ����б����롣 + FreeType �ե���ȤΥ�������̾�ϡ�����ɽ�Τ褦�� weight, style, + stretch �ץ��ѥƥ����б����롣 + +@verbatim + ��������̾ weight style stretch + ---------- ------ ----- ------- + Regular medium r normal + Italic medium i normal + Bold bold r normal + Bold Italic bold i normal + Narrow medium r condensed + Narrow Italic medium i condensed + Narrow Bold bold r condensed + Narrow Bold Italic bold i condensed + Black black r normal + Black Italic black i normal + Oblique medium o normal + BoldOblique bold o normal +@endverbatim + + ���ɽ�˸����ʤ���������̾�� "Regular" �Ȥ��ư����롣 + + platform ID �� encoding ID ���Ȥ߹�碌�� registry + �ץ��ѥƥ����б����롣���Ȥ��Ф���ե���Ȥ� (1 1) �Ȥ��� ID ���ȹ礻����ƤС� + registry �ץ��ѥƥ��� 1-1 �Ȥʤ롣���ˤˤ�������ȹ礻�ˤϰʲ��Τ褦������Ѥ� + registry �ץ��ѥƥ� ��Ϳ�����Ƥ��롣 + +@verbatim + platform ID encoding ID registry �ץ��ѥƥ� + ----------- ----------- ----------------- + 0 3 unicode-bmp + 0 4 unicode-full + 1 0 apple-roman + 3 1 unicode-bmp + 3 1 unicode-full +@endverbatim + + �������äơ���Ĥ��ȹ礻 (1 0) ��(3 1) ����ĥե���Ȥϡ����줾�� + registry �ץ��ѥƥ��� 1-0, apple-roman, 3-1, unicode-bmp + �Ǥ��룴�ĤΥե���ȥ��֥������Ȥ��б����롣 + +
  • OpenType �ե���� + + m17n �饤�֥��ϡ�FreeType �饤�֥��� OTF + �饤�֥�����Ѥ���褦�����ꤹ��С����٤Ƥ� OpenType + �ե���Ȥ򥵥ݡ��Ȥ��롣�ºݤ����ѤǤ���ե���ȤΥꥹ�Ȥ� FreeType + �ե���Ȥξ���Ʊ�ͤ˺���롣OpenType �ե���Ȥ� FLT (Font Layout Table) + ��ͳ�ǻ��Ѥ���褦�ե���ȥ��åȤ˻��ꤵ��Ƥ��ꡢFLT �� OTF + ��Ϣ�Υ��ޥ�� (���Ȥ��� otf:deva) ������С�OTF �饤�֥�꤬�ե���Ȥ� OpenType + �쥤�����ȥơ��֥�˽��ä�ʸ����򥰥�ե���������Ѵ�����FreeType + �饤�֥�꤬�ƥ���դΥӥåȥޥåץ��᡼�����󶡤��롣 + +
+ +*/ + +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include "config.h" + +#include +#include +#include +#include + +#include "m17n-gui.h" +#include "m17n-misc.h" +#include "internal.h" +#include "mtext.h" +#include "symbol.h" +#include "plist.h" +#include "charset.h" +#include "language.h" +#include "internal-gui.h" +#include "font.h" +#include "face.h" +#include "fontset.h" + +MPlist *mfont__driver_list; + +static MSymbol M_font_capability, M_font_list, M_font_list_len; + +/** Indices to font properties sorted by their priority. */ +static int font_score_priority[] = + { MFONT_SIZE, + MFONT_WEIGHT, + MFONT_STYLE, + MFONT_STRETCH, + MFONT_FAMILY, + MFONT_ADSTYLE, + MFONT_FOUNDRY + }; + +#define FONT_SCORE_PRIORITY_SIZE \ + (sizeof font_score_priority / sizeof font_score_priority[0]) + +/* Indexed by a font property MFONT_XXX, and the value is how many + bits to shift the difference of property values. */ +static int font_score_shift_bits[MFONT_SIZE + 1]; + +/** Predefined symbols for each font property. The order is important + because the function font_score () decides how well a font matches + with a spec by checking how close the index is. */ + +static char *common_foundry[] = + { "misc", + "adobe" }; +static char *common_family[] = + { "fixed", + "courier", + "helvetica", + "times" }; +static char *common_weight[] = + { "thin" + "ultralight", + "extralight", + "light", + "demilight", + "book", + "regular", + "normal", + "medium", + "demibold", + "semibold", + "bold", + "extrabold", + "ultrabold", + "black", + "heavy" }; +static char *common_style[] = + { "o", + "i", + "slanted", + "r", + "rslanted", + "ri", + "ro" }; +static char *common_stretch[] = + { "ultracondensed", + "extracondensed", + "condensed", + "narrow", + "semicondensed", + "normal", + "semiexpanded", + "expanded", + "extraexpanded", + "ultraexpanded" }; +static char *common_adstyle[] = + { "serif", + "", + "sans" }; +static char *common_registry[] = + { "iso8859-1" }; + +static unsigned short font_weight_regular; +static unsigned short font_weight_normal; +static unsigned short font_weight_medium; + +/* Table containing all the data above. */ + +struct MFontCommonNames +{ + int num; + char **names; +}; + +static struct MFontCommonNames font_common_names[] = + { + { sizeof (common_foundry) / sizeof (char *), common_foundry}, + { sizeof (common_family) / sizeof (char *), common_family}, + { sizeof (common_weight) / sizeof (char *), common_weight}, + { sizeof (common_style) / sizeof (char *), common_style}, + { sizeof (common_stretch) / sizeof (char *), common_stretch}, + { sizeof (common_adstyle) / sizeof (char *), common_adstyle}, + { sizeof (common_registry) / sizeof (char *), common_registry} + }; + + +/** Table of available font property names. */ + +MFontPropertyTable mfont__property_table[MFONT_REGISTRY + 1]; + + +/** Return the numeric value of SYMBOL as the Nth font property. */ + +#define FONT_PROPERTY_NUMERIC(symbol, n) \ + ((symbol) == Mnil \ + ? 0 \ + : ((int) msymbol_get ((symbol), mfont__property_table[(n)].property))) + + +/** Set the numeric value of SYMBOL as the Nth font property to NUMERIC. */ + +#define SET_FONT_PROPERTY_NUMERIC(symbol, n, numeric) \ + msymbol_put((symbol), mfont__property_table[(n)].property, \ + (void *) (numeric)) + + +/* Font selector. */ + +struct MFontEncoding { + MFont spec; + MSymbol encoding_name; + MCharset *encoding_charset; + MSymbol repertory_name; + MCharset *repertory_charset; +}; + +static MPlist *font_encoding_list; +static MFontEncoding default_encoding; + +/** Load font encoding table from the data . + The data has this form: + (FONT-SPEC ENCODING) ... + where FONT-SPEC has this form: + ([FOUNDRY FAMILY [WEIGHT [STYLE [STRETCH [ADSTYLE]]]]] REGISTRY) + All elements are symbols. */ + +static int +load_font_encoding_table () +{ + MDatabase *mdb; + MPlist *encoding_list, *plist, *pl, *elt; + + font_encoding_list = pl = mplist (); + + mdb = mdatabase_find (Mfont, msymbol ("encoding"), Mnil, Mnil); + if (! mdb + || ! (encoding_list = (MPlist *) mdatabase_load (mdb))) + MERROR (MERROR_FONT, -1); + + MPLIST_DO (plist, encoding_list) + { + MFontEncoding *encoding; + MSymbol registry; + + MSTRUCT_CALLOC (encoding, MERROR_FONT); + + if (! MPLIST_PLIST_P (plist) + || (elt = MPLIST_PLIST (plist), mplist_length (elt) < 2) + || ! MPLIST_PLIST_P (elt)) + MWARNING (MERROR_FONT); + registry = mfont__set_spec_from_plist (&encoding->spec, + MPLIST_PLIST (elt)); + elt = MPLIST_NEXT (elt); + if (! MPLIST_SYMBOL_P (elt)) + MWARNING (MERROR_FONT); + encoding->encoding_name = MPLIST_SYMBOL (elt); + elt = MPLIST_NEXT (elt); + if (MPLIST_TAIL_P (elt)) + encoding->repertory_name = encoding->encoding_name; + else if (! MPLIST_SYMBOL_P (elt)) + MWARNING (MERROR_FONT); + else + encoding->repertory_name = MPLIST_SYMBOL (elt); + + if (registry == Mnil) + mplist_push (font_encoding_list, Mt, encoding); + else + pl = mplist_add (pl, registry, encoding); + continue; + + warning: + free (encoding); + } + + M17N_OBJECT_UNREF (encoding_list); + return 0; +} + +typedef struct { + MFont spec; + int resize; +} MFontResize; + +static MPlist *font_resize_list; + +/** Load font size table from the data . + The data has this form: + (FONT-SPEC RESIZE-FACTOR) ... + where FONT-SPEC has this form: + ([FOUNDRY FAMILY [WEIGHT [STYLE [STRETCH [ADSTYLE]]]]] REGISTRY) + All elements of FONT-SPEC are symbols. */ + +static int +load_font_resize_table () +{ + MDatabase *mdb; + MPlist *size_adjust_list, *plist, *pl, *elt; + + font_resize_list = pl = mplist (); + + mdb = mdatabase_find (Mfont, msymbol ("resize"), Mnil, Mnil); + if (! mdb) + return -1; + if (! (size_adjust_list = (MPlist *) mdatabase_load (mdb))) + MERROR (MERROR_FONT, -1); + + MPLIST_DO (plist, size_adjust_list) + { + MFontResize *resize; + MSymbol registry; + + MSTRUCT_CALLOC (resize, MERROR_FONT); + + if (! MPLIST_PLIST_P (plist) + || (elt = MPLIST_PLIST (plist), mplist_length (elt) != 2) + || ! MPLIST_PLIST_P (elt)) + MWARNING (MERROR_FONT); + registry = mfont__set_spec_from_plist (&resize->spec, + MPLIST_PLIST (elt)); + elt = MPLIST_NEXT (elt); + if (! MPLIST_INTEGER_P (elt)) + MWARNING (MERROR_FONT); + resize->resize = MPLIST_INTEGER (elt); + + if (registry == Mnil) + registry = Mt; + pl = mplist_add (pl, registry, resize); + continue; + + warning: + free (resize); + } + + M17N_OBJECT_UNREF (size_adjust_list); + return 0; +} + +/** Return a font encoding (and repertory) of FONT. */ + +static MFontEncoding * +find_encoding (MFont *font) +{ + MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY); + MFontEncoding *encoding = NULL; + MPlist *plist; + + if (! font_encoding_list) + load_font_encoding_table (); + plist = font_encoding_list; + while (! MPLIST_TAIL_P (plist)) + { + encoding = (MFontEncoding *) MPLIST_VAL (plist); + if (mfont__match_p (font, &encoding->spec, MFONT_REGISTRY)) + { + if (encoding->encoding_name != Mnil + && ! encoding->encoding_charset) + { + encoding->encoding_charset = MCHARSET (encoding->encoding_name); + if (! encoding->encoding_charset) + { + mplist_pop (plist); + continue; + } + } + if (encoding->repertory_name == encoding->encoding_name) + encoding->repertory_charset = encoding->encoding_charset; + else if (encoding->repertory_name != Mnil) + { + encoding->repertory_charset + = MCHARSET (encoding->repertory_name); + if (! encoding->repertory_charset) + { + mplist_pop (plist); + continue; + } + } + font->encoding = encoding; + return encoding; + } + + if (registry && MPLIST_KEY (plist) != Mt) + { + plist = mplist_find_by_key (plist, registry); + if (! plist) + break; + } + else + plist = MPLIST_NEXT (plist); + } + font->encoding = &default_encoding; + return &default_encoding; +} + +#ifndef HAVE_OTF +static OTF_Tag +OTF_tag (char *name) +{ + unsigned char *p = (unsigned char *) name; + + if (! name) + return (OTF_Tag) 0; + return (OTF_Tag) ((p[0] << 24) + | (! p[1] ? 0 + : ((p[1] << 16) + | (! p[2] ? 0 + : (p[2] << 8) | p[3])))); +} + +void +OTF_tag_name (OTF_Tag tag, char *name) +{ + name[0] = (char) (tag >> 24); + name[1] = (char) ((tag >> 16) & 0xFF); + name[2] = (char) ((tag >> 8) & 0xFF); + name[3] = (char) (tag & 0xFF); + name[4] = '\0'; +} +#endif /* not HAVE_OTF */ + +/* XLFD parser/generator */ + +/** Indices to each field of split font name. */ + +enum xlfd_field_idx + { + XLFD_FOUNDRY, + XLFD_FAMILY, + XLFD_WEIGHT, + XLFD_SLANT, + XLFD_SWIDTH, + XLFD_ADSTYLE, + XLFD_PIXEL, + XLFD_POINT, + XLFD_RESX, + XLFD_RESY, + XLFD_SPACING, + XLFD_AVGWIDTH, + XLFD_REGISTRY, /* This contains ENCODING. */ + /* anchor */ + XLFD_FIELD_MAX + }; + +static int +xlfd_parse_name (const char *name, MFont *font) +{ + char *field[XLFD_FIELD_MAX]; + unsigned short resy, avgwidth; + unsigned size; + char copy[513]; + int i; + char *p; + MSymbol sym; + + if (name[0] != '-') + return -1; + + field[0] = copy; + for (i = 1, p = copy, name++; *name; p++, name++) + { + if (p - copy > 512) + return -1; + if (*name == '-' + && i < XLFD_FIELD_MAX) + { + *p = '\0'; + if (field[i - 1][0] == '*') + field[i - 1] = NULL; + field[i++] = p + 1; + } + else + *p = tolower (*name); + } + *p = '\0'; + if (field[i - 1][0] == '*') + field[i - 1] = NULL; + while (i < XLFD_FIELD_MAX) + field[i++] = NULL; + + resy = field[XLFD_RESY] ? atoi (field[XLFD_RESY]) : 0; + avgwidth = ((field[XLFD_AVGWIDTH] && isdigit (field[XLFD_AVGWIDTH][0])) + ? atoi (field[XLFD_AVGWIDTH]) : 1); + if (! avgwidth) + size = 0; + else if (! field[XLFD_PIXEL]) + size = field[XLFD_POINT] ? atoi (field[XLFD_POINT]) * resy / 72 : 0; + else if (field[XLFD_PIXEL][0] == '[') + { + /* The pixel size field specifies a transformation matrix of the + form "[A B C D]". The XLFD spec says that the scalar value N + for the pixel size is equivalent to D. */ + char *p0 = field[XLFD_PIXEL] + 1, *p1; + double d; + + for (i = 0; i < 4; i++, p0 = p1) + d = strtod (p0, &p1); + size = d * 10; + } + else + size = atoi (field[XLFD_PIXEL]) * 10; + + if (field[XLFD_FOUNDRY]) + { + sym = msymbol (field[XLFD_FOUNDRY]); + if (! sym) + sym = msymbol ("Nil"); + mfont__set_property (font, MFONT_FOUNDRY, sym); + } + if (field[XLFD_FAMILY]) + { + sym = msymbol (field[XLFD_FAMILY]); + if (! sym) + sym = msymbol ("Nil"); + mfont__set_property (font, MFONT_FAMILY, sym); + } + if (field[XLFD_WEIGHT]) + mfont__set_property (font, MFONT_WEIGHT, msymbol (field[XLFD_WEIGHT])); + if (field[XLFD_SLANT]) + mfont__set_property (font, MFONT_STYLE, msymbol (field[XLFD_SLANT])); + if (field[XLFD_SWIDTH]) + mfont__set_property (font, MFONT_STRETCH, msymbol (field[XLFD_SWIDTH])); + if (field[XLFD_ADSTYLE]) + mfont__set_property (font, MFONT_ADSTYLE, msymbol (field[XLFD_ADSTYLE])); + font->property[MFONT_RESY] = resy; + font->size = size; + if (field[XLFD_SPACING]) + font->spacing + = ((field[XLFD_SPACING][0] == 'p' || field[XLFD_SPACING][0] == 'P') + ? MFONT_SPACING_PROPORTIONAL + : (field[XLFD_SPACING][0] == 'm' || field[XLFD_SPACING][0] == 'M') + ? MFONT_SPACING_MONO : MFONT_SPACING_CHARCELL); + if (field[XLFD_REGISTRY]) + mfont__set_property (font, MFONT_REGISTRY, msymbol (field[XLFD_REGISTRY])); + font->type = MFONT_TYPE_SPEC; + font->source = MFONT_SOURCE_X; + return 0; +} + +static char * +xlfd_unparse_name (MFont *font, int full_xlfd) +{ + MSymbol prop[7]; + char name[513]; + char *str[7]; + int len, i; + char spacing; + int size, resy; + int all_nil = 1; + + prop[0] = (MSymbol) mfont_get_prop (font, Mfoundry); + prop[1] = (MSymbol) mfont_get_prop (font, Mfamily); + prop[2] = (MSymbol) mfont_get_prop (font, Mweight); + prop[3] = (MSymbol) mfont_get_prop (font, Mstyle); + prop[4] = (MSymbol) mfont_get_prop (font, Mstretch); + prop[5] = (MSymbol) mfont_get_prop (font, Madstyle); + prop[6] = (MSymbol) mfont_get_prop (font, Mregistry); + for (len = 0, i = 0; i < 7; i++) + { + if (prop[i] != Mnil) + { + str[i] = msymbol_name (prop[i]); + len += strlen (str[i]); + all_nil = 0; + } + else + { + str[i] = "*"; + len++; + } + } + spacing = (font->spacing == MFONT_SPACING_UNDECIDED ? '*' + : font->spacing == MFONT_SPACING_PROPORTIONAL ? 'p' + : font->spacing == MFONT_SPACING_MONO ? 'm' + : 'c'); + + if ((len + + 13 /* 13 dashes */ + + 2 /* 2 asterisks */ + + 30 /* 3 integers (each 10 digits) */ + + 1 /* 1 spacing char */ + + 1) /* '\0' terminal */ + > 513) + return NULL; + + resy = (int) mfont_get_prop (font, Mresolution); + size = font->size; + if (size >= 0) + { + if (font->multiple_sizes) + { + for (size = 0; size < 24; size++) + if (font->size & (1 << size)) + break; + size += 6; + } + else if ((size % 10) < 5) + size /= 10; + else + size = size / 10 + 1; + } + else + size = - size; + + if (full_xlfd) + { + if (font->size >= 0) + sprintf (name, "-%s-%s-%s-%s-%s-%s-%d-*-%d-%d-%c-*-%s", + str[0], str[1], str[2], str[3], str[4], str[5], + size, resy, resy, spacing, str[6]); + else + sprintf (name, "-%s-%s-%s-%s-%s-%s-*-%d-%d-%d-%c-*-%s", + str[0], str[1], str[2], str[3], str[4], str[5], + size, resy, resy, spacing, str[6]); + } + else if (all_nil && size == 0) + sprintf (name, "*"); + else + { + char *p = name; + + p += sprintf (p, "-%s", str[0]); + for (i = 1; i < 6; i++) + if (p[-1] != '*' || str[i][0] != '*') + p += sprintf (p, "-%s", str[i]); + if (p[-1] != '*' || font->size > 0) + { + if (font->size > 0) + p += sprintf (p, "-%d-*", size); + else + p += sprintf (p, "-*"); + } + if (str[6][0] != '*') + sprintf (p, "-%s", str[6]); + } + + return strdup (name); +} + +/* Compare FONT with REQUEST and return how much they differs. */ + +static int +font_score (MFont *font, MFont *request) +{ + int score = 0; + int i = FONT_SCORE_PRIORITY_SIZE; + + while (--i >= 0) + { + enum MFontProperty prop = font_score_priority[i]; + int val; + + if (prop == MFONT_SIZE) + { + if (font->size && request->size) + { + if (font->multiple_sizes) + { + int j, closest = 23; + + for (j = 23; j >= 0; j--) + if (font->size & (1 << j)) + { + closest = j; + if (request->size >= (j + 6) * 10) + break; + } + val = request->size - (closest + 6) * 10; + } + else + val = font->size - request->size; + if (val) + { + if (val < 0) + val = - val; + if (val >= 0x10000) + val = 0xFFFF; + score |= (val << font_score_shift_bits[MFONT_SIZE]); + } + } + } + else if (font->property[prop] && request->property[prop] + && font->property[prop] != request->property[prop]) + { + if (prop <= MFONT_FAMILY) + val = 1; + else if (prop == MFONT_WEIGHT) + { + unsigned short v1 = font->property[prop]; + unsigned short v2 = request->property[prop]; + + if (v1 == font_weight_regular || v1 == font_weight_normal) + v1 = font_weight_medium; + if (v2 == font_weight_regular || v2 == font_weight_normal) + v2 = font_weight_medium; + val = v1 > v2 ? v1 - v2 : v2 - v1; + } + else + { + val = font->property[prop] - request->property[prop]; + if (val < 0) + val = - val; + if (val > 3) + val = 3; + } + score |= val << font_score_shift_bits[prop]; + } + } + if (request->file != Mnil && request->file != font->file) + score |= 40000000; + return score; +} + +static MSymbol +merge_capability (MSymbol capability, MSymbol key, MSymbol val, int overwrite) +{ + MFontCapability *cap = NULL; + char *lang = NULL, *script = NULL, *otf = NULL, *buf, *p; + int lang_len = 0, script_len = 0, otf_len = 0; + + if (key == Mlanguage) + lang = MSYMBOL_NAME (val), lang_len = MSYMBOL_NAMELEN (val) + 6; + else if (key == Mscript) + script = MSYMBOL_NAME (val), script_len = MSYMBOL_NAMELEN (val) + 7; + else if (key == Motf) + otf = MSYMBOL_NAME (val), otf_len = MSYMBOL_NAMELEN (val) + 5; + else + return capability; + + if (capability != Mnil) + { + cap = mfont__get_capability (capability); + if (! overwrite) + { + if (cap->language) + lang = NULL; + if (cap->script) + script = NULL; + if (cap->script_tag) + otf = NULL; + if (! lang && !script && !otf) + return capability; + } + } + + if (! lang && cap && cap->language) + { + lang_len = MSYMBOL_NAMELEN (cap->language); + lang = MSYMBOL_NAME (cap->language); + } + if (! script && cap && cap->script != Mnil) + { + script_len = MSYMBOL_NAMELEN (cap->script); + script = MSYMBOL_NAME (cap->script); + } + if (! otf && cap && cap->script_tag) + { + int i; + + otf_len = 4; /* for script_tag */ + if (cap->langsys_tag) + otf_len += 5; /* for "/XXXX */ + for (i = 0; i < MFONT_OTT_MAX; i++) + if (cap->features[i].str) + otf_len += strlen (cap->features[i].str) + 1; /* for "[=+]..." */ + otf = p = alloca (otf_len + 1); + OTF_tag_name (cap->script_tag, otf); + p += 4; + if (cap->langsys_tag) + { + *p++ = '/'; + OTF_tag_name (cap->langsys_tag, p); + p += 4; + } + if (cap->features[MFONT_OTT_GSUB].str) + p += sprintf (p, "=%s", cap->features[MFONT_OTT_GSUB].str); + if (cap->features[MFONT_OTT_GPOS].str) + p += sprintf (p, "=%s", cap->features[MFONT_OTT_GSUB].str); + } + buf = p = alloca (lang_len + script_len + otf_len + 1); + if (lang_len) + p += sprintf (p, ":lang=%s", lang); + if (script_len) + p += sprintf (p, ":script=%s", script); + if (otf_len) + p += sprintf (p, ":otf=%s", otf); + return msymbol (buf); +} + + +/* Internal API */ + +MSymbol Miso8859_1, Miso10646_1, Municode_bmp, Municode_full, Mapple_roman; + +int +mfont__init () +{ + int i, shift; + MSymbol regular = msymbol ("regular"); + MSymbol normal = msymbol ("normal"); + MSymbol medium = msymbol ("medium"); + + M_font_capability = msymbol_as_managing_key (" font-capability"); + M_font_list = msymbol_as_managing_key (" font-list"); + M_font_list_len = msymbol (" font-list-len"); + + Mfoundry = msymbol ("foundry"); + mfont__property_table[MFONT_FOUNDRY].property = Mfoundry; + Mfamily = msymbol ("family"); + mfont__property_table[MFONT_FAMILY].property = Mfamily; + Mweight = msymbol ("weight"); + mfont__property_table[MFONT_WEIGHT].property = Mweight; + Mstyle = msymbol ("style"); + mfont__property_table[MFONT_STYLE].property = Mstyle; + Mstretch = msymbol ("stretch"); + mfont__property_table[MFONT_STRETCH].property = Mstretch; + Madstyle = msymbol ("adstyle"); + mfont__property_table[MFONT_ADSTYLE].property = Madstyle; + Mregistry = msymbol ("registry"); + mfont__property_table[MFONT_REGISTRY].property = Mregistry; + + Mspacing = msymbol ("spacing"); + Msize = msymbol ("size"); + Mresolution = msymbol ("resolution"); + Mmax_advance = msymbol ("max-advance"); + Mfontfile = msymbol ("fontfile"); + + Mfontconfig = msymbol ("fontconfig"); + + Mx = msymbol ("x"); + Mfreetype = msymbol ("freetype"); + Mxft = msymbol ("xft"); + + Miso8859_1 = msymbol ("iso8859-1"); + Miso10646_1 = msymbol ("iso10646-1"); + Municode_bmp = msymbol ("unicode-bmp"); + Municode_full = msymbol ("unicode-full"); + Mapple_roman = msymbol ("apple-roman"); + + Motf = msymbol ("otf"); + + /* The first entry of each mfont__property_table must be Mnil so + that actual properties get positive numeric numbers. */ + for (i = 0; i <= MFONT_REGISTRY; i++) + { + MLIST_INIT1 (&mfont__property_table[i], names, 8); + MLIST_APPEND1 (&mfont__property_table[i], names, Mnil, MERROR_FONT); + } + + /* Register predefined font property names. */ + for (i = 0; i <= MFONT_REGISTRY; i++) + { + int j; + + for (j = 0; j < font_common_names[i].num; j++) + { + MSymbol sym = msymbol (font_common_names[i].names[j]); + + if (sym == Mnil) + return -1; + if (msymbol_put (sym, mfont__property_table[i].property, + (void *) (j + 1)) < 0) + return -1; + MLIST_APPEND1 (&mfont__property_table[i], names, sym, + MERROR_FONT); + if (i == MFONT_WEIGHT) + { + if (sym == regular) + font_weight_regular = j + 1; + else if (sym == normal) + font_weight_normal = j + 1; + else if (sym == medium) + font_weight_medium = j + 1; + } + } + } + + /* Here, SHIFT starts from 1, not 0. This is because the lowest bit + of a score is a flag for a scalable font (see the documentation + of font_score). */ + i = FONT_SCORE_PRIORITY_SIZE - 1; + for (shift = 1; i >= 0; i--) + { + font_score_shift_bits[font_score_priority[i]] = shift; + if (font_score_priority[i] == MFONT_SIZE) + shift += 16; + else if (font_score_priority[i] <= MFONT_FAMILY) + shift++; + else + shift += 2; + } + + MFONT_INIT (&default_encoding.spec); + default_encoding.encoding_name = Municode_full; + default_encoding.encoding_charset = mcharset__unicode; + default_encoding.repertory_name = Mnil; + default_encoding.repertory_charset = NULL; + { + char *path, *buf = NULL; + int bufsize; + USE_SAFE_ALLOCA; + + mfont_freetype_path = mplist (); + bufsize = strlen (M17NDIR) + 7; + SAFE_ALLOCA (buf, bufsize); + sprintf (buf, "%s/fonts", M17NDIR); + mplist_add (mfont_freetype_path, Mstring, strdup (buf)); + path = getenv ("M17NDIR"); + if (path) + { + bufsize = strlen (path) + 7; + SAFE_ALLOCA (buf, bufsize); + sprintf (buf, "%s/fonts", path); + mplist_push (mfont_freetype_path, Mstring, strdup (buf)); + } + SAFE_FREE (buf); + } + +#ifdef HAVE_FREETYPE + if (mfont__ft_init () < 0) + return -1; +#endif /* HAVE_FREETYPE */ + + return 0; +} + +void +mfont__fini () +{ + MPlist *plist; + int i; + +#ifdef HAVE_FREETYPE + mfont__ft_fini (); +#endif /* HAVE_FREETYPE */ + + MPLIST_DO (plist, mfont_freetype_path) + free (MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (mfont_freetype_path); + + if (font_resize_list) + { + MPLIST_DO (plist, font_resize_list) + free (MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (font_resize_list); + font_resize_list = NULL; + } + if (font_encoding_list) + { + MPLIST_DO (plist, font_encoding_list) + free (MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (font_encoding_list); + font_encoding_list = NULL; + } + + for (i = 0; i <= MFONT_REGISTRY; i++) + MLIST_FREE1 (&mfont__property_table[i], names); +} + + +MSymbol +mfont__id (MFont *font) +{ + char *buf = NULL, *p; + int i; + int file_len = (font->file == Mnil ? 0 : MSYMBOL_NAMELEN (font->file)); + int capability_len = (font->capability == Mnil ? 0 + : MSYMBOL_NAMELEN (font->capability)); + int total_len = MFONT_PROPERTY_MAX * 5 + 9 + file_len + capability_len; + MSymbol id; + USE_SAFE_ALLOCA; + + SAFE_ALLOCA (buf, total_len); + p = buf; + if (font->property[0]) + p += sprintf (p, "%X", font->property[0]); + for (i = 1; i < MFONT_PROPERTY_MAX; i++) + { + if (font->property[i]) + p += sprintf (p, "-%X", font->property[i]); + else + *p++ = '-'; + } + if (font->size) + p += sprintf (p, "-%X", font->size); + if (font->spacing) + p += sprintf (p, "-%X", font->spacing); + if (capability_len > 0) + { + *p++ = '-'; + memcpy (p, MSYMBOL_NAME (font->capability), capability_len); + p += capability_len; + } + if (file_len > 0) + { + *p++ = '-'; + memcpy (p, MSYMBOL_NAME (font->file), file_len); + p += file_len; + } + id = msymbol__with_len (buf, p - buf); + SAFE_FREE (buf); + return id; +} + +/** Return 1 iff FONT matches SPEC. */ + +int +mfont__match_p (MFont *font, MFont *spec, int prop) +{ + if (spec->capability != font->capability + && spec->capability != Mnil) + { + MRealizedFont *rfont; + + if (font->type != MFONT_TYPE_REALIZED) + return (font->capability == Mnil); + rfont = (MRealizedFont *) font; + return (rfont->driver->check_capability + && (rfont->driver->check_capability (rfont, spec->capability) + >= 0)); + } + if (spec->file != font->file + && spec->file != Mnil && font->file != Mnil) + return 0; + for (; prop >= 0; prop--) + if (spec->property[prop] && font->property[prop] + && font->property[prop] != spec->property[prop]) + return 0; + return 1; +} + +/* Merge SRC into DST. If error_on_conflict is nonzero and a font + property differs in SRC and DST, return -1. */ + +int +mfont__merge (MFont *dst, MFont *src, int error_on_conflict) +{ + int i; + + for (i = 0; i < MFONT_PROPERTY_MAX; i++) + { + if (! dst->property[i]) + dst->property[i] = src->property[i]; + else if (error_on_conflict + && src->property[i] + && dst->property[i] != src->property[i]) + return -1; + } + if (! dst->spacing) + dst->spacing = src->spacing; + else if (error_on_conflict + && src->spacing + && dst->spacing != src->spacing) + return -1; + if (! dst->size) + dst->size = src->size; + else if (error_on_conflict + && src->size + && dst->size != src->size) + return -1; + if (dst->capability == Mnil) + dst->capability = src->capability; + else if (error_on_conflict + && src->capability + && dst->capability != src->capability) + return -1; + if (dst->file == Mnil) + dst->file = src->file; + else if (error_on_conflict + && src->file + && dst->file != src->file) + return -1; + return 0; +} + +void +mfont__set_spec_from_face (MFont *spec, MFace *face) +{ + int i; + + for (i = 0; i <= MFONT_ADSTYLE; i++) + mfont__set_property (spec, i, face->property[i]); + spec->property[MFONT_REGISTRY] = 0; + spec->property[MFONT_RESY] = 0; + spec->multiple_sizes = 0; + spec->size = (int) (face->property[MFACE_SIZE]); + spec->type = MFONT_TYPE_SPEC; + spec->source = MFONT_SOURCE_UNDECIDED; + spec->file = spec->capability = Mnil; + spec->encoding = NULL; +} + + +extern MSymbol +mfont__set_spec_from_plist (MFont *spec, MPlist *plist) +{ + int i; + MSymbol spec_list[MFONT_REGISTRY + 1]; + MSymbol registry; + char *reg; + + MFONT_INIT (spec); + memset (spec_list, 0, sizeof spec_list); + for (i = 0; ! MPLIST_TAIL_P (plist); i++, plist = MPLIST_NEXT (plist)) + { + if (! MPLIST_SYMBOL_P (plist)) + MERROR (MERROR_FONT, Mnil); + spec_list[i] = MPLIST_SYMBOL (plist); + } + if (i == 0) + MERROR (MERROR_FONT, Mnil); + registry = spec_list[i - 1]; + if (i > 1 && registry != Mnil) + { + reg = MSYMBOL_NAME (registry); + if (reg[0] == ':') + { + mfont__get_capability (registry); + spec->capability = registry; + registry = spec_list[i - 2]; + i--; + } + } + mfont__set_property (spec, MFONT_REGISTRY, registry); + for (i -= 2; i >= 0; i--) + mfont__set_property (spec, i, spec_list[i]); + spec->type = MFONT_TYPE_SPEC; + + return registry; +} + + +MFont * +mfont__select (MFrame *frame, MFont *font, int max_size) +{ + MFontDriver *driver; + + if (font->type == MFONT_TYPE_FAILURE) + return NULL; + if (font->type != MFONT_TYPE_SPEC) + return font; + if (font->source == MFONT_SOURCE_UNDECIDED) + { + if (font->file != Mnil || font->capability != Mnil) + font->source = MFONT_SOURCE_FT; + else if (font->property[MFONT_REGISTRY]) + { + MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY); + char *reg = MSYMBOL_NAME (registry); + + if (strncmp (reg, "unicode-", 8) == 0 + || strncmp (reg, "apple-roman", 11) == 0 + || (reg[0] >= '0' && reg[0] <= '9' && reg[1] == '-')) + font->source = MFONT_SOURCE_FT; + } + } + if (font->source != MFONT_SOURCE_FT) + { + driver = mplist_get (frame->font_driver_list, Mx); + if (driver) + return (driver->select) (frame, font, max_size); + } + driver = mplist_get (frame->font_driver_list, Mfreetype); + if (! driver) + return NULL; + return (driver->select) (frame, font, max_size); +} + + +int +mfont__available (MFrame *frame, MFont *font) +{ + return -1; +} + +static int +compare_font_score (const void *e1, const void *e2) +{ + MFontScore *s1 = (MFontScore *) e1, *s2 = (MFontScore *) e2; + + return (s1->font->for_full_width == s2->font->for_full_width + ? s1->score > s2->score + : s1->font->for_full_width); +} + +void +mdebug_dump_font_list (MFontList *font_list) +{ + int i; + + for (i = 0; i < font_list->nfonts; i++) + { + fprintf (mdebug__output, "%04X - ", font_list->fonts[i].score); + mdebug_dump_font (font_list->fonts[i].font); + fprintf (mdebug__output, "\n"); + } +} + +void +mfont__free_realized (MRealizedFont *rfont) +{ + MRealizedFont *next; + + for (; rfont; rfont = next) + { + next = rfont->next; + M17N_OBJECT_UNREF (rfont->info); + free (rfont); + rfont = next; + } +} + +MFontList * +mfont__list (MFrame *frame, MFont *spec, MFont *request, int max_size) +{ + MFontList *list; + MSymbol id = mfont__id (spec); + MPlist *pl, *p; + int num, i; + + pl = msymbol_get (id, M_font_list); + if (pl) + num = (int) msymbol_get (id, M_font_list_len); + else + { + pl = mplist (); + num = 0; + MPLIST_DO (p, frame->font_driver_list) + { + if (spec->source == MFONT_SOURCE_X ? MPLIST_KEY (p) == Mx + : spec->source == MFONT_SOURCE_FT ? MPLIST_KEY (p) == Mfreetype + : 1) + { + MFontDriver *driver = MPLIST_VAL (p); + num += (driver->list) (frame, pl, spec, 0); + } + } + msymbol_put (id, M_font_list, pl); + M17N_OBJECT_UNREF (pl); + msymbol_put (id, M_font_list_len, (void *) num); + } + + if (num == 0) + return NULL; + + MSTRUCT_MALLOC (list, MERROR_FONT); + MTABLE_MALLOC (list->fonts, num, MERROR_FONT); + for (i = 0; num > 0; num--, pl = MPLIST_NEXT (pl)) + { + MFont *font = MPLIST_VAL (pl), *adjusted = font; + + if (max_size == 0 + || font->size == 0 + || font->size < max_size) + { + list->fonts[i].font = font; + if (spec == request) + list->fonts[i].score = 0; + else + { + int resize_ratio; + MFont resized; + + if (font->size > 0 + && (resize_ratio = mfont_resize_ratio (font)) != 100) + { + resized = *font; + resized.size = font->size * 100 / resize_ratio; + adjusted = &resized; + } + list->fonts[i].score = font_score (adjusted, request); + } + i++; + } + } + if (i == 0) + { + free (list->fonts); + free (list); + return NULL; + } + list->nfonts = i; + if (spec != request) + qsort (list->fonts, i, sizeof (MFontScore), compare_font_score); + list->object = *spec; + mfont__merge (&list->object, request, 0); + list->object.type = MFONT_TYPE_OBJECT; + return list; +} + +/** Open a font specified in FONT. */ + +MRealizedFont * +mfont__open (MFrame *frame, MFont *font, MFont *spec) +{ + MFontDriver *driver; + MRealizedFont *rfont; + + if (font->source == MFONT_SOURCE_UNDECIDED) + MFATAL (MERROR_FONT); + if (font->type != MFONT_TYPE_OBJECT) + MFATAL (MERROR_FONT); + for (rfont = MPLIST_VAL (frame->realized_font_list); rfont; + rfont = rfont->next) + { + driver = rfont->driver; + if (rfont->font == font + && mplist_find_by_value (frame->font_driver_list, driver)) + break; + } + + if (! rfont) + { + driver = mplist_get (frame->font_driver_list, + font->source == MFONT_SOURCE_X ? Mx : Mfreetype); + if (! driver) + MFATAL (MERROR_FONT); + } + return (driver->open) (frame, font, spec, rfont); +} + +int +mfont__has_char (MFrame *frame, MFont *font, MFont *spec, int c) +{ + MFontEncoding *encoding; + unsigned code; + MFontDriver *driver; + + if (font->source == MFONT_SOURCE_UNDECIDED) + MFATAL (MERROR_FONT); + encoding = (font->encoding ? font->encoding : find_encoding (font)); + if (! encoding->encoding_charset) + return 0; + if (encoding->repertory_charset) + { + code = ENCODE_CHAR (encoding->repertory_charset, c); + return (code != MCHAR_INVALID_CODE); + } + code = ENCODE_CHAR (encoding->encoding_charset, c); + if (code == MCHAR_INVALID_CODE) + return 0; + if (font->type == MFONT_TYPE_REALIZED) + driver = ((MRealizedFont *) font)->driver; + else + { + driver = mplist_get (frame->font_driver_list, + font->source == MFONT_SOURCE_X ? Mx : Mfreetype); + if (! driver) + MFATAL (MERROR_FONT); + } + return (driver->has_char) (frame, font, spec, c, code); +} + +unsigned +mfont__encode_char (MFrame *frame, MFont *font, MFont *spec, int c) +{ + MFontEncoding *encoding; + unsigned code; + MFontDriver *driver; + + if (font->source == MFONT_SOURCE_UNDECIDED) + MFATAL (MERROR_FONT); + encoding = (font->encoding ? font->encoding : find_encoding (font)); + if (! encoding->encoding_charset) + return MCHAR_INVALID_CODE; + if (font->source == MFONT_SOURCE_X && encoding->repertory_charset) + return (ENCODE_CHAR (encoding->repertory_charset, c)); + code = ENCODE_CHAR (encoding->encoding_charset, c); + if (code == MCHAR_INVALID_CODE) + return MCHAR_INVALID_CODE; + if (font->type == MFONT_TYPE_REALIZED) + driver = ((MRealizedFont *) font)->driver; + else + { + driver = mplist_get (frame->font_driver_list, + font->source == MFONT_SOURCE_X ? Mx : Mfreetype); + if (! driver) + MFATAL (MERROR_FONT); + } + return (driver->encode_char) (frame, font, spec, code); +} + +void +mfont__get_metric (MGlyphString *gstring, int from, int to) +{ + MGlyph *from_g = MGLYPH (from), *to_g = MGLYPH (to), *g; + MRealizedFont *rfont = from_g->rface->rfont; + + for (g = from_g; ; g++) + if (g == to_g || g->rface->rfont != rfont) + { + int idx = GLYPH_INDEX (g); + + (rfont->driver->find_metric) (rfont, gstring, from, idx); + while (from_g < g) + { + from_g->g.xadv >>= 6; + from_g->g.yadv >>= 6; + from_g->g.xoff >>= 6; + from_g->g.yoff >>= 6; + from_g->g.ascent >>= 6; + from_g->g.descent >>= 6; + from_g->g.lbearing >>= 6; + from_g->g.rbearing >>= 6; + from_g++; + } + if (g == to_g) + break; + rfont = g->rface->rfont; + from = idx; + } +} + +int +mfont__get_glyph_id (MFLTFont *font, MFLTGlyphString *gstring, + int from, int to) +{ + MFont *mfont = (MFont *) ((MFLTFontForRealized *) font)->rfont; + MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont; + MFontEncoding *encoding; + MFontDriver *driver = NULL; + MGlyph *glyphs = (MGlyph *) gstring->glyphs; + int result = 0; + + encoding = mfont->encoding ? mfont->encoding : find_encoding (mfont); + for (; from < to; from++) + { + MGlyph *g = glyphs + from; + + if (g->g.encoded) + continue; + if (mfont->source == MFONT_SOURCE_X && encoding->repertory_charset) + g->g.code = ENCODE_CHAR (encoding->repertory_charset, g->g.c); + else + { + unsigned code; + + if (encoding->encoding_charset) + code = ENCODE_CHAR (encoding->encoding_charset, g->g.c); + else + code = g->g.code; + + if (code != MCHAR_INVALID_CODE) + { + if (! driver) + { + if (mfont->type == MFONT_TYPE_REALIZED) + driver = rfont->driver; + else + { + driver = mplist_get (rfont->frame->font_driver_list, + mfont->source == MFONT_SOURCE_X + ? Mx : Mfreetype); + if (! driver) + MFATAL (MERROR_FONT); + } + } + g->g.code = (driver->encode_char) (rfont->frame, rfont->font, + mfont, code); + } + } + g->g.encoded = 1; + if (g->g.code == MCHAR_INVALID_CODE) + result = -1; + } + return result; +} + +int +mfont__get_metrics (MFLTFont *font, MFLTGlyphString *gstring, + int from, int to) +{ + MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont; + MGlyphString gstr; + + gstr.glyphs = (MGlyph *) gstring->glyphs; + (rfont->driver->find_metric) (rfont, &gstr, from, to); + return 0; +} + +/* KEY <= MFONT_REGISTRY */ + +void +mfont__set_property (MFont *font, enum MFontProperty key, MSymbol val) +{ + int numeric; + + if (val == Mnil) + numeric = 0; + else + { + numeric = FONT_PROPERTY_NUMERIC (val, key); + if (! numeric) + { + numeric = mfont__property_table[key].used; + MLIST_APPEND1 (mfont__property_table + key, names, val, MERROR_FONT); + SET_FONT_PROPERTY_NUMERIC (val, key, numeric); + } + } + font->property[key] = numeric; +} + +int +mfont__parse_name_into_font (const char *name, MSymbol format, MFont *font) +{ + int result = -1; + + if (format == Mx || format == Mnil) + result = xlfd_parse_name (name, font); +#ifdef HAVE_FONTCONFIG + if (format == Mfontconfig || (result < 0 && format == Mnil)) + result = mfont__ft_parse_name (name, font); +#endif /* HAVE_FONTCONFIG */ + return result; +} + +MPlist * +mfont__encoding_list (void) +{ + if (! font_encoding_list) + load_font_encoding_table (); + return font_encoding_list; +} + +static void +free_font_capability (void *object) +{ + MFontCapability *cap = object; + + if (cap->script_tag) + { + int i; + for (i = 0; i < MFONT_OTT_MAX; i++) + { + if (cap->features[i].str) + free (cap->features[i].str); + if (cap->features[i].tags) + free (cap->features[i].tags); + } + } + free (cap); +} + +MFontCapability * +mfont__get_capability (MSymbol sym) +{ + MFontCapability *cap = msymbol_get (sym, M_font_capability); + char *str, *p, *endp; + + if (cap) + return cap; + str = MSYMBOL_NAME (sym); + if (str[0] != ':') + return NULL; + M17N_OBJECT (cap, free_font_capability, MERROR_FONT); + msymbol_put (sym, M_font_capability, cap); + M17N_OBJECT_UNREF (cap); + endp = str + MSYMBOL_NAMELEN (sym); + while (str < endp) + { + if (*str++ != ':') + continue; + if (str[0] == 'o' && strncmp (str + 1, "tf=", 3) == 0) + { + char *beg; + MSymbol sym; + int i; + + str += 4; + beg = str; + for (i = 0, p = str; i < 4 && p < endp; i++, p++); + if (i < 4) + break; + sym = msymbol__with_len (str, 4); + cap->script = mscript__from_otf_tag (sym); + if (cap->script == Mnil) + break; + cap->script_tag = OTF_tag (str); + if (*p == '/') + { + for (i = 0, str = ++p; i < 4 && p < endp; i++, p++); + if (i < 4) + { + cap->script = Mnil; + cap->script_tag = 0; + break; + } + cap->langsys_tag = OTF_tag (str); + } + else + cap->langsys_tag = 0; + + for (i = 0; i < MFONT_OTT_MAX; i++) + cap->features[i].nfeatures = -1; + + while (*p == '=' || *p == '+') + { + int idx = *p == '=' ? MFONT_OTT_GSUB : MFONT_OTT_GPOS; + + str = ++p; + while (p < endp && *p != '+') p++; + if (str < p) + { + int n; + /* We never have more than (p - str) tags. */ + OTF_Tag *tags = alloca (sizeof (OTF_Tag) * (p - str)); + char *p0; + + cap->features[idx].str = malloc (p - str + 1); + for (i = n = 0, p0 = str; str + i < p; i++) + { + cap->features[idx].str[i] = str[i]; + if (str[i] == ',' || str + i + 1 == p) + { + if (*p0 == '*') + tags[n] = 0; + else if (*p0 == '~') + tags[n] = OTF_tag (p0 + 1) | 0x80000000; + else + tags[n] = OTF_tag (p0); + n++; + p0 = str + i + 1; + } + } + cap->features[idx].str[i] = '\0'; + cap->features[idx].nfeatures = n; + if (n > 0) + { + int size = sizeof (OTF_Tag) * n; + + cap->features[idx].tags = malloc (size); + memcpy (cap->features[idx].tags, tags, size); + } + } + else + { + cap->features[idx].str = NULL; + cap->features[idx].nfeatures = 0; + } + } + + for (i = 0; i < MFONT_OTT_MAX; i++) + if (cap->features[i].nfeatures < 0) + { + cap->features[i].str = strdup ("*"); + cap->features[i].nfeatures = 1; + cap->features[i].tags = malloc (sizeof (OTF_Tag)); + cap->features[i].tags[0] = 0; + } + cap->otf = msymbol__with_len (beg, p - beg); + str = p; + } + else if (str[0] == 'l' && strncmp (str + 1, "ang=", 4) == 0) + { + str += 5; + for (p = str; p < endp && *p != ':'; p++); + if (str < p) + cap->language = msymbol__with_len (str, p - str); + str = p; + } + else if (str[0] == 's' && strncmp (str + 1, "cript=", 6) == 0) + { + str += 7; + for (p = str; p < endp && *p != ':'; p++); + if (str < p) + cap->script = msymbol__with_len (str, p - str); + str = p; + } + } + return cap; +} + +int +mfont__check_capability (MRealizedFont *rfont, MSymbol capability) +{ + return (rfont->driver->check_capability (rfont, capability)); +} + + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + + +/* External API */ + +/*** @addtogroup m17nFont */ +/*** @{ */ +/*=*/ + +/***en @name Variables: Keys of font property. */ +/***ja @name �ѿ�: �ե���ȥץ��ѥƥ�����ꤹ������Ѥߥ���ܥ� */ +/*** @{ */ +/*=*/ + +/***en + @brief Key of font property specifying foundry. + + The variable #Mfoundry is a symbol of name "foundry" and + is used as a key of font property and face property. The property + value must be a symbol whose name is a foundry name of a font. */ +/***ja + @brief ��ȯ������ꤹ��ե���ȥץ��ѥƥ��Υ���. + + �ѿ� #Mfoundry �� "foundry" + �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ��ѥƥ��ȥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣 + �ͤϡ��ե���Ȥγ�ȯ��̾��̾���Ȥ��ƻ��ĥ���ܥ�Ǥ��롣 */ + +MSymbol Mfoundry; + +/***en + @brief Key of font property specifying family. + + The variable #Mfamily is a symbol of name "family" and is + used as a key of font property and face property. The property + value must be a symbol whose name is a family name of a font. */ +/***ja + @brief �ե��ߥ����ꤹ��ե���ȥץ��ѥƥ��Υ���. + + �ѿ� #Mfamily �� "family" + �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ��ѥƥ��ȥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣 + �ͤϡ��ե���ȤΥե��ߥ�̾��̾���Ȥ��ƻ��ĥ���ܥ�Ǥ��롣 */ + +MSymbol Mfamily; + +/***en + @brief Key of font property specifying weight. + + The variable #Mweight is a symbol of name "weight" and is + used as a key of font property and face property. The property + value must be a symbol whose name is a weight name of a font (e.g + "medium", "bold"). */ +/***ja + @brief ��������ꤹ��ե���ȥץ��ѥƥ��Υ���. + + �ѿ� #Mweight �� "weight" + �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ��ѥƥ��ȥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣 + �ͤϡ��ե���Ȥ�����̾ ( "medium", "bold" ��) ��̾���Ȥ��ƻ��ĥ���ܥ�Ǥ��롣 */ + +MSymbol Mweight; + +/***en + @brief Key of font property specifying style. + + The variable #Mstyle is a symbol of name "style" and is + used as a key of font property and face property. The property + value must be a symbol whose name is a style name of a font (e.g + "r", "i", "o"). */ +/***ja + @brief �����������ꤹ��ե���ȥץ��ѥƥ��Υ���. + + �ѿ� #Mstyle �� "style" + �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ��ѥƥ��ȥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣 + �ͤϡ��ե���ȤΥ�������̾ ("r", "i", "o" ��)��̾���Ȥ��ƻ��ĥ���ܥ�Ǥ��롣 */ + +MSymbol Mstyle; + +/***en + @brief Key of font property specifying stretch. + + The variable #Mstretch is a symbol of name "stretch" and + is used as a key of font property and face property. The property + value must be a symbol whose name is a stretch name of a font (e.g + "normal", "condensed"). */ +/***ja + @brief ������ꤹ��ե���ȥץ��ѥƥ��Υ���. + + �ѿ� #Mstretch �� "stretch" + �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ��ѥƥ��ȥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣 + �ͤϡ��ե���Ȥ�ʸ����̾ ( "normal", "condensed" ��)��̾���Ȥ��ƻ��ĥ���ܥ�Ǥ��롣 */ + +MSymbol Mstretch; + +/***en + @brief Key of font property specifying additional style. + + The variable #Madstyle is a symbol of name "adstyle" and + is used as a key of font property and face property. The property + value must be a symbol whose name is an additional style name of a + font (e.g "serif", "", "sans"). */ +/***ja + @brief adstyle ����ꤹ��ե���ȥץ��ѥƥ��Υ���. + + �ѿ� #Madstyle �� "adstyle" + �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ��ѥƥ��ȥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣 + �ͤϡ��ե���Ȥ� adstyle ̾("serif", "", "sans" ��)��̾���Ȥ��ƻ��ĥ���ܥ�Ǥ��롣 */ + +MSymbol Madstyle; + +/***en + @brief Key of font property specifying spacing. + + The variable #Madstyle is a symbol of name "spacing" and + is used as a key of font property. The property value must be a + symbol whose name specifies the spacing of a font (e.g "p" for + proportional, "m" for monospaced). */ +/***ja + @brief spacing ����ꤹ��ե���ȥץ��ѥƥ��Υ���. + + �ѿ� #Mspacing �� "spacing" �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ + �ե���ȥץ��ѥƥ��Υ����Ȥ����Ѥ����롣�ͤϡ��ե���Ȥ� spacing + �����򼨤�̾�� ("p", "m" ��)����ĥ���ܥ�Ǥ��롣 */ + +MSymbol Mspacing; + +/***en + @brief Key of font property specifying registry. + + The variable #Mregistry is a symbol of name "registry" + and is used as a key of font property. The property value must be + a symbol whose name is a registry name a font registry + (e.g. "iso8859-1", "jisx0208.1983-0"). */ +/***ja + @brief �쥸���ȥ����ꤹ��ե���ȥץ��ѥƥ��Υ���. + + �ѿ� #Mregistry �� "registry" + �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ��ѥƥ��ȥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣 + �ͤϡ��ե���ȤΥ쥸���ȥ�̾ ( "iso8859-1", "jisx0208.1983-0" + ��) ��̾���Ȥ��ƻ��ĥ���ܥ�Ǥ��롣 */ + +MSymbol Mregistry; + +/***en + @brief Key of font property specifying size. + + The variable #Msize is a symbol of name "size" and is + used as a key of font property and face property. The property + value must be an integer specifying a font design size in the unit + of 1/10 point (on 100 dpi display). */ +/***ja + @brief ����������ꤹ��ե���ȥץ��ѥƥ��Υ���. + + �ѿ� #Msize �� "size" + �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ��ѥƥ��ȥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣�ͤϡ� + 100 dpi �Υǥ����ץ쥤��ǤΥե���ȤΥǥ����󥵥����� 1/10 + �ݥ����ñ�̤Ǽ��������ͤǤ��롣 + */ + +MSymbol Msize; + +/***en + @brief Key of font property specifying file name. + + The variable #Mfontfile is a symbol of name "fontfile" + and is used as a key of font property. The property value must be + a symbol whose name is a font file name. */ +MSymbol Motf; + +/***en + @brief Key of font property specifying file name. + + The variable #Mfontfile is a symbol of name "fontfile" + and is used as a key of font property. The property value must be + a symbol whose name is a font file name. */ +/***ja + @brief �ե���ȥե��������ꤹ��ե���ȥץ��ѥƥ��Υ���. + + �ѿ� #Mfontfile �� "fontfile" �Ȥ���̾������ĥ���ܥ�Ǥ� + �ꡢ�ե���ȥץ��ѥƥ��Υ����Ȥ����Ѥ����롣�ͤϡ��ե���ȥե��� + ��̾��̾���Ȥ��ƻ��ĤȤ��륷��ܥ�Ǥ��롣 */ + +MSymbol Mfontfile; + +/***en + @brief Key of font property specifying resolution. + + The variable #Mresolution is a symbol of name "resolution" and + is used as a key of font property and face property. The property + value must be an integer to specifying a font resolution in the + unit of dots per inch (dpi). */ +/***ja + @brief �����٤���ꤹ��ե���ȥץ��ѥƥ��Υ���. + + �ѿ� #Mresolution �� "resolution" + �Ȥ���̾������ĥ���ܥ�Ǥ��ꡢ�ե���ȥץ��ѥƥ��ȥե������ץ��ѥƥ��Υ����Ȥ����Ѥ����롣 + �ͤϡ��ե���Ȥβ����٤� dots per inch (dpi) ñ�̤Ǽ��������ͤǤ��롣 */ + +MSymbol Mresolution; + +/***en + @brief Key of font property specifying max advance width. + + The variable #Mmax_advance is a symbol of name + "max-advance" and is used as a key of font property. The + property value must be an integer specifying a font's max advance + value by pixels. */ + +MSymbol Mmax_advance; + + +/***en + @brief Symbol of name "fontconfig". + + The variable #Mfontconfig is to be used as an argument of the + functions mfont_parse_name () and mfont_unparse_name (). */ +/***ja + @brief "fontconfig" �Ȥ���̾������ĥ���ܥ�. + + �ѿ� #Mfontconfig �ϴؿ� mfont_parse_name () �� mfont_unparse_name () + �ΰ����Ȥ����Ѥ����롣 */ + +MSymbol Mfontconfig; + +/***en + @brief Symbol of name "x". + + The variable #Mx is to be used for a value of \ member of the + structure #MDrawGlyph to specify the type of \ member is + actually (XFontStruct *). */ +/***ja + @brief "x" �Ȥ���̾������ĥ���ܥ�. + + �ѿ� #Mx �Ϲ�¤ #MDrawGlyph �Υ��� \ + ���ͤȤ����Ѥ���졢���� \ �η����ºݤˤ� (XFontStruct *) �Ǥ��뤳�Ȥ�ɽ��. */ + +MSymbol Mx; + +/***en + @brief Symbol of name "freetype". + + The variable #Mfreetype is to be used for a value of \ member + of the structure #MDrawGlyph to specify the type of \ member + is actually FT_Face. */ +/***ja + @brief "freetype" �Ȥ���̾������ĥ���ܥ�. + + �ѿ� #Mfreetype �Ϲ�¤ #MDrawGlyph �Υ��� \ + ���ͤȤ����Ѥ���졢���� \ �η����ºݤˤ� FT_Face �Ǥ��뤳�Ȥ�ɽ���� */ + +MSymbol Mfreetype; + +/***en + @brief Symbol of name "xft". + + The variable #Mxft is to be used for a value of \ member of the + structure #MDrawGlyph to specify the type of \ member + is actually (XftFont *). */ +/***ja + @brief "xft" �Ȥ���̾������ĥ���ܥ�. + + �ѿ� #Mxft �Ϲ�¤ #MDrawGlyph �Υ��� \ + ���ͤȤ����Ѥ���졢���� \ �η����ºݤˤ� (XftFont *) �Ǥ��뤳�Ȥ�ɽ���� */ + +MSymbol Mxft; + +/*=*/ +/*** @} */ +/*=*/ + +/***en + @brief List of font files and directories that contain font files. + + The variable @c mfont_freetype_path is a plist of FreeType font + files and directories that contain FreeType font files. Key of + the element is @c Mstring, and the value is a string that + represents a font file or a directory. + + The macro M17N_INIT () sets up this variable to contain the + sub-directory "fonts" of the m17n database and the environment + variable "M17NDIR". The first call of mframe () creates the + internal list of the actually available fonts from this variable. + Thus, an application program, if necessary, must modify the + variable before calling mframe (). If it is going to add a new + element, value must be a string that can be safely freed. + + If the m17n library is not configured to use the FreeType library, + this variable is not used. */ +/***ja + @brief �ե���ȥե�����ȥե���ȥե������ޤ�ǥ��쥯�ȥ�Υꥹ��. + + �ѿ� @c mfont_freetype_path �ϡ��ե���ȥե�����ȥե���ȥե������ޤ�ǥ��쥯�ȥ�� + plist �Ǥ��롣�����ǤΥ����� @c Mstring + �Ǥ��ꡢ�ͤϥե���ȥե����뤫�ǥ��쥯�ȥ�򼨤�ʸ����Ǥ��롣 + + �ޥ��� M17N_INIT () �ˤ�äơ������ѿ��� m17n �ǡ����١����ȴĶ��ѿ� + "M17NDIR" �����Υ��֥ǥ��쥯�ȥ� "fonts" ��ޤ�褦�����ꤵ��롣 + mframe () �κǽ�θƤӽФ��κݤˡ������ѿ�����ºݤ˻��ѤǤ���ե���Ȥ������ꥹ�Ȥ�����롣 + �����ǥ��ץꥱ�������ץ������ϡ�mframe () + ��Ƥ����ˡ�ɬ�פʤ�Сˤ����ѿ����ѹ����ʤ��ƤϤʤ�ʤ��� + ���������Ǥ��ɲä�����ˤϡ������ͤϰ����˳����Ǥ���ʸ����Ǥʤ��ƤϤʤ�ʤ��� + + m17n �饤�֥�꤬ FreeType �饤�֥���Ȥ��褦�����ꤵ��Ƥʤ����ˤϡ������ѿ����Ѥ����ʤ��� */ + +MPlist *mfont_freetype_path; + +/*=*/ + +/***en + @brief Create a new font. + + The mfont () function creates a new font object that has no + property. + + @return + This function returns a pointer to the created font object. */ +/***ja + @brief �������ե���Ȥ���. + + �ؿ� mfont () �ϥץ��ѥƥ�����ڻ����ʤ��������ե���Ȥ򥪥֥������Ȥ��롣 + + @return + ���δؿ��Ϻ�ä��ե���ȥ��֥������ȤؤΥݥ��󥿤��֤��� */ + +MFont * +mfont () +{ + MFont *font; + + MSTRUCT_CALLOC (font, MERROR_FONT); + return font; +} + +/*=*/ + +/***en + @brief Create a font by parsing a fontname. + + The mfont_parse_name () function creates a new font object. The + properties are extracted fontname $NAME. + + $FORMAT specifies the format of $NAME. If $FORMAT is #Mx, $NAME + is parsed as XLFD (X Logical Font Description). If $FORMAT is + #Mfontconfig, $NAME is parsed as Fontconfig's textual + representation of font. If $FORMAT is #Mnil, $NAME is at first + parsed as XLFD, and it it fails, parsed as Fontconfig's + representation. + + @return + If the operation was successful, this function returns a pointer + to the created font. Otherwise it returns @c NULL. */ + +/***ja + @brief �ե����̾����ե���Ȥ���. + + �ؿ� mfont_parse_name () �ϡ��ե����̾ + $NAME ������Ф��줿�ץ��ѥƥ�����ġ��������ե���ȥ��֥������Ȥ��롣 + + $FORMAT �� $NAME �Υե����ޥåȤ���ꤹ�롣$FORMAT �� #Mx �Ǥ���С� + $NAME �� XLFD (X Logical Font Description) �˽��äƲ��Ϥ���롣 + $FORMAT �� #Mfontconfig �Ǥ���� $NAME �� Fontfonfig + �Υե���ȥƥ�����ɽ���˽��äƲ��Ϥ���롣$FORMAT �� #Mnil �Ǥ���С��ޤ� XLFD + �˽��äƲ��Ϥ��졢����˼��Ԥ����� Fontconfig �˽��äƲ��Ϥ���롣 + + @return + ��������������� mfont_parse_name () + �Ͽ��������줿�ե���ȤؤΥݥ��󥿤��֤��������Ǥʤ���� @c NULL ���֤��� */ + +MFont * +mfont_parse_name (const char *name, MSymbol format) +{ + MFont template, *font; + + MFONT_INIT (&template); + if (mfont__parse_name_into_font (name, format, &template) < 0) + MERROR (MERROR_FONT, NULL); + MSTRUCT_CALLOC (font, MERROR_FONT); + *font = template; + return font; +} + +/*=*/ + +/***en + @brief Create a fontname from a font. + + The mfont_unparse_name () function creates a fontname string + from font $FONT according to $FORMAT. + + $FORMAT must be #Mx or #Mfontconfig. If it is #Mx, the fontname + is in XLFD (X Logical Font Description) format. If it is + #Mfontconfig, the fontname is in the style of Fontconfig's text + representation. + + @return + This function returns a newly allocated fontname string, which is + not freed unless the user explicitly does so by free (). */ + +/***ja + @brief �ե���Ȥ���ե����̾����. + + �ؿ� mfont_unparse_name () �� �ե����̾��ʸ�����ե���� $FONT + �򸵤�$FORMAT �˽��äƺ�롣 + + $FORMAT �� #Mx �ޤ��� #Mfontconfig �Ǥ��롣 + #Mx �ʤ�Хե����̾�� XLFD (X Logical Font Description) �˽����� + #Mfontconfig �ʤ�Хե����̾�� Fontconfig �Υե���ȥƥ�����ɽ���˽����� + + @return + ���δؿ��Ͽ����˥��������Ȥ����ե����̾��ʸ������֤���ʸ����ϡ��桼���� + free () �ˤ�ä�����Ū�˲������ʤ��¤��������ʤ��� */ + +char * +mfont_unparse_name (MFont *font, MSymbol format) +{ + char *name; + + if (format == Mx) + name = xlfd_unparse_name (font, 1); +#ifdef HAVE_FONTCONFIG + else if (format == Mfontconfig) + name = mfont__ft_unparse_name (font); + +#endif /* HAVE_FONTCONFIG */ + else + MERROR (MERROR_FONT, NULL); + return name; +} + +/*=*/ + +/***en + @brief Make a copy of a font. + + The mfont_copy () function returns a new copy of font $FONT. */ +/***ja + @brief �ե���ȤΥ��ԡ�����. + + �ؿ� Mfont_copy () �ϥե���� $FONT �Υ��ԡ����ꡢ������֤��� */ + +MFont * +mfont_copy (MFont *font) +{ + MFont *copy; + + MSTRUCT_MALLOC (copy, MERROR_FONT); + *copy = *font; + return copy; +} + +/*=*/ + +/***en + @brief Get a property value of a font. + + The mfont_get_prop () function gets the value of $KEY property of + font $FONT. $KEY must be one of the following symbols: + + @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, + @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing. + + If $FONT is a return value of mfont_find (), $KEY can also be one + of the following symbols: + + @b Mfont_ascent, @b Mfont_descent, #Mmax_advance. + + @return + If $KEY is @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, + @c Mstretch, @c Madstyle, @c Mregistry, or @c Mspacing, this + function returns the corresponding value as a symbol. If the font + does not have $KEY property, it returns @c Mnil. If $KEY is @c + Msize, @c Mresolution, @b Mfont_ascent, Mfont_descent, or + #Mmax_advance, this function returns the corresponding value as an + integer. If the font does not have $KEY property, it returns 0. + If $KEY is something else, it returns @c NULL and assigns an error + code to the external variable #merror_code. */ + +/***ja + @brief �ե���ȤΥץ��ѥƥ����ͤ�����. + + �ؿ� mfont_get_prop () �ϥե���� $FONT �Υץ��ѥƥ��Τ����������� + $KEY �Ǥ����Τ��ͤ��֤���$KEY �ϰʲ��Υ���ܥ�Τ����줫�Ǥʤ��� + �Фʤ�ʤ��� + + @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, + @c Madstyle, @c Mregistry, @c Msize, @c Mresolution, @c Mspacing. + + @return + $KEY �� @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c + Mstretch, @c Madstyle, @c Mregistry, @c Mspacing �Τ����줫�Ǥ���С� + ���������ͤ򥷥�ܥ�Ȥ����֤����ե���Ȥ����Υץ��ѥƥ�������ʤ� + ���ˤ�@c Mnil ���֤���$KEY �� @c Msize ���뤤�� @c Mresolution �� + ���ˤϡ����������ͤ�������ͤȤ����֤����ե���Ȥ����Υץ��ѥƥ� + ������ʤ����ˤ� 0 ���֤���$KEY ������ʳ��Τ�ΤǤ���С�@c + NULL ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +void * +mfont_get_prop (MFont *font, MSymbol key) +{ + MRealizedFont *rfont = NULL; + + if (font->type == MFONT_TYPE_REALIZED) + rfont = (MRealizedFont *) font; + + if (key == Mfoundry) + return (void *) FONT_PROPERTY (font, MFONT_FOUNDRY); + if (key == Mfamily) + return (void *) FONT_PROPERTY (font, MFONT_FAMILY); + if (key == Mweight) + return (void *) FONT_PROPERTY (font, MFONT_WEIGHT); + if (key == Mstyle) + return (void *) FONT_PROPERTY (font, MFONT_STYLE); + if (key == Mstretch) + return (void *) FONT_PROPERTY (font, MFONT_STRETCH); + if (key == Madstyle) + return (void *) FONT_PROPERTY (font, MFONT_ADSTYLE); + if (key == Mregistry) + return (void *) FONT_PROPERTY (font, MFONT_REGISTRY); + if (key == Msize) + { + int size = font->size; + return (void *) size; + } + if (key == Mresolution) + { + int resy = font->property[MFONT_RESY]; + return (void *) resy; + } + if (key == Mlanguage || key == Mscript || key == Motf) + { + MFontCapability *cap; + + if (! font->capability) + return NULL; + cap = mfont__get_capability (font->capability); + if (key == Mlanguage) + return cap->language; + if (key == Mscript) + return cap->script; + return cap->otf; + } + + if (key == Mfontfile) + return (void *) font->file; + if (key == Mspacing) + return (font->spacing == MFONT_SPACING_UNDECIDED ? Mnil + : msymbol (font->spacing == MFONT_SPACING_PROPORTIONAL ? "p" + : font->spacing == MFONT_SPACING_MONO ? "m" : "c")); + if (rfont) + { + if (key == Mfont_ascent) + return (void *) rfont->ascent; + if (key == Mfont_descent) + return (void *) rfont->descent; + if (key == Mmax_advance) + return (void *) rfont->max_advance; + } + MERROR (MERROR_FONT, NULL); +} + + +/*=*/ +/***en + @brief Put a property value to a font. + + The mfont_put_prop () function puts a font property whose key is + $KEY and value is $VAL to font $FONT. $KEY must be one of the + following symbols: + + @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, + @c Madstyle, @c Mregistry, @c Msize, @c Mresolution. + + If $KEY is @c Msize or @c Mresolution, $VAL must be an integer. + Otherwise, $VAL must be a symbol of a property value name. But, + if the name is "nil", a symbol of name "Nil" must be + specified. */ + /***ja + @brief �ե���ȤΥץ��ѥƥ����ͤ����ꤹ��. + + �ؿ� mfont_put_prop () �ϡ��ե���� $FONT �Υ�����$KEY �Ǥ���ץ��� + �ƥ����ͤ� $VAL �����ꤹ�롣$KEY �ϰʲ��Υ���ܥ�Τ����줫�Ǥ��롣 + + @c Mfoundry, @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, + @c Madstyle, @c Mregistry, @c Msize, @c Mresolution. + + $KEY �� @c Msize �� @c Mresolution �Ǥ���� $VAL �������ͤǤʤ��Ƥ� + ��ʤ�������ʳ��ξ�硢$VAL �ϥץ��ѥƥ��ͤ�̾���Υ���ܥ�Ǥʤ��� + �Ϥʤ�ʤ����������⤷����̾���� "nil" �ξ��ϡ�̾���� "Nil" �Υ� + ��ܥ�Ǥʤ��ƤϤʤ�ʤ���*/ + +int +mfont_put_prop (MFont *font, MSymbol key, void *val) +{ + if (key == Mfoundry) + mfont__set_property (font, MFONT_FOUNDRY, (MSymbol) val); + else if (key == Mfamily) + mfont__set_property (font, MFONT_FAMILY, (MSymbol) val); + else if (key == Mweight) + mfont__set_property (font, MFONT_WEIGHT, (MSymbol) val); + else if (key == Mstyle) + mfont__set_property (font, MFONT_STYLE, (MSymbol) val); + else if (key == Mstretch) + mfont__set_property (font, MFONT_STRETCH, (MSymbol) val); + else if (key == Madstyle) + mfont__set_property (font, MFONT_ADSTYLE, (MSymbol) val); + else if (key == Mregistry) + mfont__set_property (font, MFONT_REGISTRY, (MSymbol) val); + else if (key == Msize) + { + int size = (int) val; + font->size = size; + } + else if (key == Mresolution) + { + unsigned resy = (unsigned) val; + font->property[MFONT_RESY] = resy; + } + else if (key == Mlanguage || key == Mscript || key == Motf) + { + font->capability = merge_capability (font->capability, + key, (MSymbol) val, 1); + } + else if (key == Mfontfile) + { + font->file = (MSymbol) val; + } + else + MERROR (MERROR_FONT, -1); + return 0; +} + +/*=*/ + +/***en + @brief Return the font selection priority. + + The mfont_selection_priority () function returns a newly created + array of six symbols. The elements are the following + keys of font properties ordered by priority. + + @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, + @c Madstyle, @c Msize. + + The m17n library selects the best matching font according to the + order of this array. A font that has a different value for a + property of lower priority is preferred to a font that has a + different value for a property of higher priority. */ +/***ja + @brief �ե���������ͥ���٤��֤�. + + �ؿ� mfont_selection_priority () �� 6 �ĤΥ���ܥ뤫��ʤ�������ä��֤��� + ��������Ǥϡ��ʲ��Υե���ȥץ��ѥƥ��Υ�����ͥ���ٽ���¤٤���ΤǤ��롣 + + @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, + @c Madstyle, @c Msize. + + m17n �饤�֥��Ϥ�������˽��äơ��Ǥ���פ���ե���Ȥ����򤹤롣 + ��Ū�Υե���Ȥȡ����줾��㤦�ץ��ѥƥ����ͤ����פ��ʤ��ե���Ȥ����ä���硢ͥ���٤��㤤�ץ��ѥƥ����ͤ����פ��ʤ��ե���ȡ�ͥ���٤ι⤤�ץ��ѥƥ����ͤ����פ��Ƥ���ե���ȡˤ����򤵤�롣 + + */ + +MSymbol * +mfont_selection_priority () +{ + MSymbol *keys; + int i; + + MTABLE_MALLOC (keys, FONT_SCORE_PRIORITY_SIZE, MERROR_FONT); + for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++) + { + enum MFontProperty prop = font_score_priority[i]; + + if (prop == MFONT_SIZE) + keys[i] = Msize; + else if (prop == MFONT_ADSTYLE) + keys[i] = Madstyle; + else if (prop == MFONT_FAMILY) + keys[i] = Mfamily; + else if (prop == MFONT_WEIGHT) + keys[i] = Mweight; + else if (prop == MFONT_STYLE) + keys[i] = Mstyle; + else if (prop == MFONT_STRETCH) + keys[i] = Mstretch; + else + keys[i] = Mfoundry; + } + return keys; +} + +/*=*/ + +/***en + @brief Set the font selection priority. + + The mfont_set_selection_priority () function sets font selection + priority according to $KEYS, which is an array of six symbols. + Each element must be one of the below. No two elements must be + the same. + + @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, + @c Madstyle, @c Msize. + + See the documentation of the function mfont_selection_priority () + for details. */ +/***ja + @brief �ե��������ͥ���٤����ꤹ��. + + �ؿ� mfont_set_selection_priority () �ϡ�6�ĤΥ���ܥ������ $KEYS + �ˤ������äƥե��������ͥ���٤����ꤹ�롣����ϰʲ��γ����Ǥ�Ŭ�� + �ʽ��֤��¤٤���ΤǤ��롣 + + @c Mfamily, @c Mweight, @c Mstyle, @c Mstretch, + @c Madstyle, @c Msize. + + �ܺ٤ϴؿ� mfont_selection_priority () �������򻲾ȤΤ��ȡ� + */ + +int +mfont_set_selection_priority (MSymbol *keys) +{ + int priority[FONT_SCORE_PRIORITY_SIZE]; + int i, j, shift; + + for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++, keys++) + { + enum MFontProperty prop; + + if (*keys == Msize) + prop = MFONT_SIZE; + else if (*keys == Madstyle) + prop = MFONT_ADSTYLE; + else if (*keys == Mfamily) + prop = MFONT_FAMILY; + else if (*keys == Mweight) + prop = MFONT_WEIGHT; + else if (*keys == Mstyle) + prop = MFONT_STYLE; + else if (*keys == Mstretch) + prop = MFONT_STRETCH; + else if (*keys == Mfoundry) + prop = MFONT_FOUNDRY; + else + /* Invalid element. */ + return -1; + for (j = 0; j < i; j++) + if (priority[j] == prop) + /* Duplicated element. */ + return -1; + priority[i] = prop; + } + for (i = 0; i < FONT_SCORE_PRIORITY_SIZE; i++) + font_score_priority[i] = priority[i]; + /* Here, SHIFT starts from 1, not 0. This is because the lowest bit + of a score is a flag for a scalable font (see the documentation + of font_score). */ + i = FONT_SCORE_PRIORITY_SIZE - 1; + for (shift = 1; i >= 0; i--) + { + font_score_shift_bits[font_score_priority[i]] = shift; + if (font_score_priority[i] == MFONT_SIZE) + shift += 16; + else if (font_score_priority[i] <= MFONT_FAMILY) + shift++; + else + shift += 2; + } + return 0; +} + +/*=*/ + +/***en + @brief Find a font. + + The mfont_find () function returns a pointer to the available font + that matches best the specification $SPEC on frame $FRAME. + + $SCORE, if not NULL, must point to a place to store the score + value that indicates how well the found font matches to $SPEC. The + smaller score means a better match. */ +/***ja + @brief �ե���Ȥ�õ��. + + �ؿ� mfont_find () �ϡ��ե졼�� $FRAME ��ǥե������� $SPEC + �ˤ�äȤ���פ������Ѳ�ǽ�ʥե���ȤؤΥݥ��󥿤��֤��� + + $SCORE �� NULL �Ǥ��뤫�����Ĥ��ä��ե���Ȥ� $SPEC + �ˤɤ�ۤɹ�äƤ��뤫�򼨤�����������¸������ؤΥݥ��󥿤Ǥ��롣 + ���������������ۤ��ɤ���äƤ��뤳�Ȥ��̣���롣 + */ + +MFont * +mfont_find (MFrame *frame, MFont *spec, int *score, int max_size) +{ + MFont spec_copy; + MFont *best; + MFontList *list; + MRealizedFont *rfont; + MFont adjusted; + + if (spec->size < 0) + { + double pt = - spec->size; + + adjusted = *spec; + adjusted.size = pt * frame->dpi / 72.27 + 0.5; + spec = &adjusted; + } + MFONT_INIT (&spec_copy); + spec_copy.property[MFONT_FAMILY] = spec->property[MFONT_FAMILY]; + spec_copy.property[MFONT_REGISTRY] = spec->property[MFONT_REGISTRY]; + spec_copy.capability = spec->capability; + spec_copy.file = spec->file; + + list = mfont__list (frame, &spec_copy, spec, max_size); + if (! list) + return NULL; + + best = list->fonts[0].font; + if (score) + *score = list->fonts[0].score; + free (list->fonts); + free (list); + spec_copy = *best; + mfont__merge (&spec_copy, spec, 0); + rfont = mfont__open (frame, best, spec); + if (! rfont) + return NULL; + return (MFont *) rfont; +} + +/*=*/ +/***en + @brief Set encoding of a font. + + The mfont_set_encoding () function sets the encoding information + of font $FONT. + + $ENCODING_NAME is a symbol representing a charset that has the + same encoding as the font. + + $REPERTORY_NAME is @c Mnil or a symbol representing a charset that + has the same repertory as the font. If it is @c Mnil, whether a + specific character is supported by the font is asked to each font + driver. + + @return + If the operation was successful, this function returns 0. + Otherwise it returns -1 and assigns an error code to the external + variable #merror_code. */ +/***ja + @brief �ե���ȤΥ��󥳡��ǥ��󥰤����ꤹ��. + + �ؿ� mfont_set_encoding () �ϥե���� $FONT �Υ��󥳡��ǥ��󥰾�������ꤹ�롣 + + $ENCODING_NAME �ϥե���Ȥ�Ʊ�����󥳡��ǥ��󥰤����ʸ�����åȤ򼨤�����ܥ�Ǥ��롣 + + $REPERTORY_NAME �� @c Mnil �Ǥ��뤫���ե���Ȥ�Ʊ�����󥳡��ǥ��󥰤����ʸ�����åȤ򼨤�����ܥ�Ǥ��롣 + @c Mnil �Ǥ���С��ġ���ʸ�������Υե���Ȥǥ��ݡ��Ȥ���Ƥ��뤫�ɤ����ϡ��ơ��Υե���ȥɥ饤�Ф��䤤��碌�롣 + + @return + ��������������Ф��δؿ��� 0 ���֤��������Ǥʤ���� -1 ���֤��������ѿ� + #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + + +int +mfont_set_encoding (MFont *font, MSymbol encoding_name, MSymbol repertory_name) +{ + MCharset *encoding_charset = MCHARSET (encoding_name); + MCharset *repertory_charset; + MSymbol registry; + MFontEncoding *encoding; + MPlist *plist; + + if (! encoding_charset) + MERROR (MERROR_FONT, -1); + if (repertory_name != Mnil) + { + repertory_charset = MCHARSET (repertory_name); + if (! repertory_charset) + MERROR (MERROR_FONT, -1); + } + else + repertory_charset = NULL; + + MSTRUCT_CALLOC (encoding, MERROR_FONT); + encoding->spec = *font; + encoding->encoding_name = encoding_name; + encoding->encoding_charset = encoding_charset; + encoding->repertory_name = repertory_name; + encoding->repertory_charset = repertory_charset; + registry = FONT_PROPERTY (font, MFONT_REGISTRY); + if (registry == Mnil) + registry = Mt; + if (! font_encoding_list) + load_font_encoding_table (); + mplist_push (font_encoding_list, registry, encoding); + MPLIST_DO (plist, MPLIST_NEXT (font_encoding_list)) + if (! memcmp (font, &((MFontEncoding *) MPLIST_VAL (plist))->spec, + sizeof (MFont))) + { + mplist_pop (plist); + break; + } + return 0; +} + +/*=*/ + +/***en + @brief Create a fontname from a font. + + This function is obsolete. Use mfont_unparse_name instead. */ +/***ja + @brief �ե����̾����ե���Ȥ���. + + ���δؿ����ѻ�ͽ��Ǥ��롣 mfont_unparse_name () ����ѤΤ��ȡ� */ + +char * +mfont_name (MFont *font) +{ + return mfont_unparse_name (font, Mx); +} + +/*=*/ + +/***en + @brief Create a new font from fontname. + + This function is obsolete. Use mfont_parse_name () instead. */ + +/***ja + @brief �ե���Ȥ���ե����̾����. + + ����ϴؿ����ѻ�ͽ��Ǥ��롣 mfont_parse_name () ����ѤΤ��ȡ� */ + +MFont * +mfont_from_name (const char *name) +{ + return mfont_parse_name (name, Mx); +} + +/*=*/ + +/***en + @brief Get resize information of a font. + + The mfont_resize_ratio () function lookups the m17n database + \ and returns a resizing ratio (in percentage) of + FONT. For instance, if the return value is 150, that means that + the m17n library uses an 1.5 time bigger font than a specified + size. */ + +/***ja + @brief �ե���ȤΥꥵ������������� + + �ؿ� mfont_resize_ratio �� m17n �ǡ����١��� \ + �򸡺������ե���� FONT �Υꥵ��������Ψ�ʥѡ�����ơ����� + ���֤������Ȥ����֤��ͤ� 150 �Ǥ���С�m17n �饤�֥��ϻ��ꤵ�줿�������� 1.5 + �ܤΥե���Ȥ���Ѥ��뤳�Ȥ��̣���롣 */ + +int +mfont_resize_ratio (MFont *font) +{ + MSymbol registry = FONT_PROPERTY (font, MFONT_REGISTRY); + MFontResize *resize; + MPlist *plist; + + if (! font_resize_list) + load_font_resize_table (); + if (! MPLIST_TAIL_P (font_resize_list)) + while (1) + { + plist = font_resize_list; + while (registry ? (plist = mplist_find_by_key (plist, registry)) + : plist) + { + resize = (MFontResize *) MPLIST_VAL (plist); + if (mfont__match_p (font, &resize->spec, MFONT_ADSTYLE)) + return resize->resize; + plist = MPLIST_NEXT (plist); + } + if (registry == Mt) + break; + registry = Mt; + } + return 100; +} + +/*=*/ + +/***en + @brief Get a list of fonts. + + The mfont_list () functions returns a list of fonts available on + frame $FRAME. $FONT, if not NULL, limits fonts to ones + that match with $FONT. $LANGUAGE, if not @c Mnil, limits fonts to + ones that support $LANGUAGE. $MAXNUM, if greater than 0, limits + the number of fonts. + + $LANGUAGE argument exists just for backward compatibility, and the + use is deprecated. Use #Mlanguage font property instead. If + $FONT already has #Mlanguage property, $LANGUAGE is ignored. + + @return + This function returns a plist whose keys are family names and + values are pointers to the object MFont. The plist must be freed + by m17n_object_unref (). If no font is found, it returns + NULL. */ + +/***ja + @brief �ե���ȤΥꥹ�Ȥ����� + + �ؿ� mfont_list () �ϥե졼�� $FRAME �����Ѳ�ǽ�ʥե���ȤΥꥹ�Ȥ� + �֤���$FONT �� NULL �Ǥʤ���С�$FONT �ȹ��פ������Ѳ�ǽ�ʥե���� + �Υꥹ�Ȥ��֤���$LANGUAGE �� @c Mnil �Ǥʤ���С�$LANGUAGE �򥵥ݡ� + �Ȥ������Ѳ�ǽ�ʥե���ȤΥꥹ�Ȥ��֤���$MAXNUM �ϡ�0 ����礭���� + ��ˤϡ��֤��ե���Ȥο��ξ�¤Ǥ��롣 + + ������������ $LANGUAGE �ϵ��ǤȤ��������Τ�������ˤ��ꡢ���λ��Ѥ� + ������ʤ����ե���Ȥ� #Mlanguage �ץ��ѥƥ���Ȥ��٤��Ǥ��롣�� + �� $FONT �����Ǥˤ��Υץ��ѥƥ�����äƤ����顢���� $LANGUAGE ��̵ + + + @return + ���δؿ��ϥ������ե���ȥե��ߥ�̾�Ǥ����ͤ� MFont ���֥������Ȥؤ� + �ݥ��󥿤Ǥ���褦��plist ���֤���plist �� m17n_object_unref () �� + ��������ɬ�פ����롣�ե���Ȥ����Ĥ���ʤ����NULL ���֤��� */ + +MPlist * +mfont_list (MFrame *frame, MFont *font, MSymbol language, int maxnum) +{ + MPlist *plist, *pl; + MFontList *font_list; + int i; + MFont spec; + + if (font) + spec = *font; + else + MFONT_INIT (&spec); + + if (spec.size < 0) + { + double pt = - spec.size; + + spec.size = pt * frame->dpi / 72.27 + 0.5; + } + + if (language != Mnil) + spec.capability = merge_capability (spec.capability, Mlanguage, language, + 0); + + font_list = mfont__list (frame, &spec, &spec, 0); + if (! font_list) + return NULL; + if (font_list->nfonts == 0) + { + free (font_list); + return NULL; + } + + plist = pl = mplist (); + for (i = 0; i < font_list->nfonts; i++) + { + MSymbol family = FONT_PROPERTY (font_list->fonts[i].font, MFONT_FAMILY); + + if (family != Mnil) + pl = mplist_add (pl, family, font_list->fonts[i].font); + } + free (font_list); + return plist; +} + +/***en + @brief Get a list of font famiy names. + + The mfont_list_family_names () functions returns a list of font + family names available on frame $FRAME. + + @return + + This function returns a plist whose keys are #Msymbol and values + are symbols representing font family names. The elements are + sorted by alphabetical order. The plist must be freed by + m17n_object_unref (). If not font is found, it returns NULL. */ + +MPlist * +mfont_list_family_names (MFrame *frame) +{ + MPlist *plist = mplist (), *p; + + MPLIST_DO (p, frame->font_driver_list) + { + MFontDriver *driver = MPLIST_VAL (p); + + (driver->list_family_names) (frame, plist); + } + return plist; +} + + +/*=*/ + +/***en + @brief Check the usability of a font. + + The mfont_check () function checkes if $FONT can be used for + $SCRIPT and $LANGUAGE in $FONTSET on $FRAME. + + @return + If the font is usable, return 1. Otherwise return 0. + */ + +int +mfont_check (MFrame *frame, MFontset *fontset, + MSymbol script, MSymbol language, MFont *font) +{ + MRealizedFont *rfont; + int best, score; + + if (! fontset) + fontset = frame->face->property[MFACE_FONTSET]; + rfont = mfontset__get_font (frame, fontset, script, language, font, &best); + if (! rfont || ! best) + return 0; + score = font_score (&rfont->spec, font); + return (score == 0 ? 2 : 1); +} + +/*=*/ + +/***en + @brief Check is a font matches with a font spec. + + The mfont_match_p () function checks if $FONT matches with the + font-spec $SPEC. + + @return + If the font matches, 1 is returned. Otherwise 0 is returned. */ + +int +mfont_match_p (MFont *font, MFont *spec) +{ + return mfont__match_p (font, spec, MFONT_REGISTRY); +} + +/*=*/ +/***en + @brief Open a font. + + The mfont_open () function opens $FONT on $FRAME, and returns a + realized font. + + @return + If the font was successfully opened, a realized font is returned. + Otherwize NULL is returned. + + @seealso + mfont_close (). */ + + +MFont * +mfont_open (MFrame *frame, MFont *font) +{ + enum MFontType font_type = font->type; + + if (font_type == MFONT_TYPE_SPEC) + return mfont_find (frame, font, NULL, 0); + if (font_type == MFONT_TYPE_OBJECT) + return (MFont *) mfont__open (frame, font, font); + if (font_type == MFONT_TYPE_REALIZED) + return font; + MERROR (MERROR_FONT, NULL); +} + +/*=*/ +/***en + @brief Encapusulate a font. + + The mfont_encapsulate () functions realizes a font by + encapusulating data $DATA or type $DATA_TYPE on $FRAME. Currently + $DATA_TAPE is #Mfontconfig or #Mfreetype, and $DATA points to an + object of FcPattern or FT_Face respectively. + + @return + If the operation was successful, a realized font is returned. + Otherwise NULL is return. + + @seealso + mfont_close (). */ + + +MFont * +mfont_encapsulate (MFrame *frame, MSymbol data_type, void *data) +{ + MPlist *p; + + MPLIST_DO (p, frame->font_driver_list) + { + MFontDriver *driver = MPLIST_VAL (p); + MRealizedFont *rfont; + + if (driver->encapsulate + && (rfont = driver->encapsulate (frame, data_type, data))) + return (MFont *) rfont; + } + + return NULL; +} + +/*=*/ +/***en + @brief Close a font. + + The mfont_close () function close a realized font $FONT. $FONT + must be opened previously by mfont_open () or mfont_encapsulate + (). + + @return + If the operation was successful, 0 is returned. Otherwise, -1 is + returned. + + @seealso + mfont_open (), mfont_encapsulate (). */ + +int +mfont_close (MFont *font) +{ + enum MFontType font_type = font->type; + MRealizedFont *rfont; + + if (font_type != MFONT_TYPE_REALIZED) + MERROR (MERROR_FONT, -1); + rfont = (MRealizedFont *) font; + if (rfont->encapsulating + && rfont->driver->close) + rfont->driver->close (rfont); + return 0; +} + +/*** @} */ + +/*** @addtogroup m17nDebug */ +/*=*/ +/*** @{ */ + +/***en + @brief Dump a font. + + The mdebug_dump_font () function prints font $FONT in a human + readable way to the stderr or to what specified by the environment + variable MDEBUG_OUTPUT_FILE. + + @return + This function returns $FONT. */ +/***ja + @brief �ե���Ȥ����פ���. + + �ؿ� mdebug_dump_font () �ϥե���� $FONT ��ɸ�२�顼���Ϥ⤷���� + �Ķ��ѿ� MDEBUG_DUMP_FONT �ǻ��ꤵ�줿�ե�����˿ʹ֤˲��ɤʷ��ǽ� + �Ϥ��롣 + + @return + ���δؿ��� $FONT ���֤��� */ + +MFont * +mdebug_dump_font (MFont *font) +{ + char *name; + + name = xlfd_unparse_name (font, 0); + if (name) + { + fprintf (mdebug__output, "%s", name); + free (name); + } + if (font->file != Mnil) + { + char *file = MSYMBOL_NAME (font->file); + char *lastslash = file, *p; + + for (p = file; *p; p++) + if (*p == '/') + lastslash = p; + if (name) + fprintf (mdebug__output, ","); + fprintf (mdebug__output, "%s", lastslash + 1); + } + if (font->capability != Mnil) + fprintf (mdebug__output, "%s", MSYMBOL_NAME (font->capability)); + return font; +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/font.h b/src/font.h new file mode 100644 index 0000000..016aa16 --- /dev/null +++ b/src/font.h @@ -0,0 +1,375 @@ +/* font.h -- header file for the font module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_FONT_H_ +#define _M17N_FONT_H_ + +enum MFontProperty + { + /* The order of MFONT_FOUNDRY to MFONT_ADSTYLE must be the same as + enum MFaceProperty. */ + MFONT_FOUNDRY, + MFONT_FAMILY, + MFONT_WEIGHT, + MFONT_STYLE, + MFONT_STRETCH, + MFONT_ADSTYLE, + MFONT_REGISTRY, + MFONT_RESY, + /* The follwoings should not be used as an index to + MFont->propperty. */ + MFONT_SIZE, + MFONT_SPACING, + /* anchor */ + MFONT_PROPERTY_MAX = MFONT_SIZE + }; + +enum MFontType + { + MFONT_TYPE_SPEC, + MFONT_TYPE_OBJECT, + MFONT_TYPE_REALIZED, + MFONT_TYPE_FAILURE + }; + +enum MFontSource + { + MFONT_SOURCE_UNDECIDED = 0, + MFONT_SOURCE_X = 1, + MFONT_SOURCE_FT = 2 + }; + +enum MFontSpacing + { + MFONT_SPACING_UNDECIDED, + MFONT_SPACING_PROPORTIONAL, + MFONT_SPACING_MONO, + MFONT_SPACING_CHARCELL + }; + +typedef struct MFontEncoding MFontEncoding; +typedef struct MFontDriver MFontDriver; + +/** Information about a font. This structure is used in three ways: + FONT-OBJ, FONT-OPENED, and FONT-SPEC. + + FONT-OBJ: To store information of an existing font. Instances + appear only in of MDisplay. + + FONT-OPENED: To store information of an opened font. Instances + appear only in of MDisplay. + + FONT-SPEC: To store specifications of a font. Instances appear + only in of MFontset. */ + +struct MFont +{ + /** Numeric value of each font property. Also used as an index to + the table @c mfont__property_table to get the actual name of the + property. + + For FONT-OBJ, FONT-OPENED: The value is greater than zero. + + For FONT-SPEC: The value is equal to or greater than zero. Zero + means that the correponding property is not specified (i.e. wild + card). + + For FONT-OBJ: If the value is 0, the font is scalable or + auto-scaled. + + For FONT-OPENED: The actual size of opened font. + + [MFONT_RESY] is the designed resolution of the font in + DPI, or zero. Zero means that the font is scalable. + + For the time being, we mention only Y-resolution (resy) and + assume that resx is always equal to resy. */ + unsigned short property[MFONT_PROPERTY_MAX]; + unsigned type : 2; + unsigned source : 2; + unsigned spacing : 2; + unsigned for_full_width : 1; + /* For FONT-OBJ, 1 means `size' is a logical or of bit masks for + available pixel sizes (Nth bit corresponds to (6 + N) pixels), 0 + means `size' is an actual pixel size * 10. For FONT-SPEC and + FONT-OPENED, this is always 0, and `size' is an actual pixel + size * 10. */ + unsigned multiple_sizes : 1; + unsigned size : 24; + MSymbol file; + MSymbol capability; + MFontEncoding *encoding; +}; + +typedef struct +{ + int size, inc, used; + MSymbol property; + MSymbol *names; +} MFontPropertyTable; + +extern MFontPropertyTable mfont__property_table[MFONT_REGISTRY + 1]; + +/** Return the symbol of the Nth font property of FONT. */ +#define FONT_PROPERTY(font, n) \ + (mfont__property_table[(n)].names[(font)->property[(n)]]) + +struct MRealizedFont +{ + /* Font spec used to find the font. + MRealizedFont::spec.property[MFONT_TYPE] is MFONT_TYPE_REALIZED + so that this object can be distingushed from MFont. */ + MFont spec; + + /* Font identifier. */ + MSymbol id; + + /* Frame on which the font is realized. */ + MFrame *frame; + + /* The found font. */ + MFont *font; + + MFontDriver *driver; + + /* Font Layout Table for the font. This is just a container to + carry the infomation. */ + MSymbol layouter; + + /* 1 iff the font is opend by encapsulating client-side font data. */ + int encapsulating; + + /* Extra information set by MRealizedFont::driver->open. If + non-NULL, it must be a pointer to a managed object. */ + void *info; + + int x_ppem, y_ppem; + + int ascent, descent, max_advance, average_width, baseline_offset; + + /* Pointer to the font structure. */ + void *fontp; + + MRealizedFont *next; +}; + +typedef struct MFLTFontForRealized { + MFLTFont font; + MRealizedFont *rfont; +} MFLTFontForRealized; + +typedef struct { + MFont *font; + int score; +} MFontScore; + +/** Structure to hold a list of fonts. */ + +typedef struct +{ + MFont object; + MFontScore *fonts; + int nfonts; +} MFontList; + +struct MFontDriver +{ + /** Return a font best matching with FONT. */ + MFont *(*select) (MFrame *frame, MFont *font, int limited_size); + + /** Open a font specified by RFONT. */ + MRealizedFont *(*open) (MFrame *frame, MFont *font, MFont *spec, + MRealizedFont *rfont); + + /** Set metrics of glyphs in GSTRING from FROM to TO. */ + void (*find_metric) (MRealizedFont *rfont, MGlyphString *gstring, + int from, int to); + + /** Check if the font has a glyph for CODE. CODE is a code point of + a character in font->encoder->encoding_charset. Return nonzero + iff the font has the glyph. */ + int (*has_char) (MFrame *frame, MFont *font, MFont *spec, + int c, unsigned code); + + /** Encode CODE into a glyph code the font. CODE is a code point of + a character in rfont->encoder->encoding_charset. If the font + has no glyph for CODE, return MCHAR_INVALID_CODE. */ + unsigned (*encode_char) (MFrame *frame, MFont *font, MFont *spec, + unsigned code); + + /** Draw glyphs from FROM to TO (exclusive) on window WIN of FRAME + at coordinate (X, Y) relative to WIN. */ + void (*render) (MDrawWindow win, int x, int y, + MGlyphString *gstring, MGlyph *from, MGlyph *to, + int reverse, MDrawRegion region); + + /** Push to PLIST fonts matching with FONT. MAXNUM if greater than + 0 limits the number of listed fonts. Return the number of fonts + listed. */ + int (*list) (MFrame *frame, MPlist *plist, MFont *font, int maxnum); + + /** Push to PLIST font family names (symbol) available on FRAME. */ + void (*list_family_names) (MFrame *frame, MPlist *plist); + + /** Check if RFONT support CAPABILITY. */ + int (*check_capability) (MRealizedFont *rfont, MSymbol capability); + + /** Open a font by encapsulating DATA. */ + MRealizedFont *(*encapsulate) (MFrame *frame, MSymbol source, void *data); + + void (*close) (MRealizedFont *rfont); + + int (*check_otf) (MFLTFont *font, MFLTOtfSpec *spec); + + int (*drive_otf) (MFLTFont *font, MFLTOtfSpec *spec, + MFLTGlyphString *in, int from, int to, + MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment); + + int (*try_otf) (MFLTFont *font, MFLTOtfSpec *spec, + MFLTGlyphString *in, int from, int to); + + int (*iterate_otf_feature) (struct _MFLTFont *font, MFLTOtfSpec *spec, + int from, int to, unsigned char *table); +}; + +/** Initialize the members of FONT. */ + +#define MFONT_INIT(font) memset ((font), 0, sizeof (MFont)) + +extern MSymbol Mlayouter; +extern MSymbol Miso8859_1, Miso10646_1, Municode_bmp, Municode_full; +extern MSymbol Mapple_roman; + +extern int mfont__flt_init (); + +extern void mfont__flt_fini (); + +#ifdef HAVE_FREETYPE +#include +#include FT_FREETYPE_H +#endif + +#ifdef HAVE_FONTCONFIG +#include +#endif + +#ifdef HAVE_OTF +#include +#else /* not HAVE_OTF */ +typedef unsigned OTF_Tag; +#endif /* not HAVE_OTF */ + +enum MFontOpenTypeTable + { + MFONT_OTT_GSUB, + MFONT_OTT_GPOS, + MFONT_OTT_MAX + }; + +typedef struct +{ + M17NObject control; + MSymbol language; + MSymbol script; + MSymbol otf; + OTF_Tag script_tag; + OTF_Tag langsys_tag; + struct { + char *str; + int nfeatures; + OTF_Tag *tags; + } features[MFONT_OTT_MAX]; +} MFontCapability; + +#ifdef HAVE_FREETYPE +extern MFontDriver mfont__ft_driver; + +extern int mfont__ft_init (); + +extern void mfont__ft_fini (); + +extern int mfont__ft_parse_name (const char *name, MFont *font); + +extern char *mfont__ft_unparse_name (MFont *font); + +#ifdef HAVE_OTF + +extern int mfont__ft_drive_otf (MGlyphString *gstring, int from, int to, + MFontCapability *capability); + +extern int mfont__ft_decode_otf (MGlyph *g); + +#endif /* HAVE_OTF */ + +#endif /* HAVE_FREETYPE */ + +extern void mfont__free_realized (MRealizedFont *rfont); + +extern int mfont__match_p (MFont *font, MFont *spec, int prop); + +extern int mfont__merge (MFont *dst, MFont *src, int error_on_conflict); + +extern void mfont__set_spec_from_face (MFont *spec, MFace *face); + +extern MSymbol mfont__set_spec_from_plist (MFont *spec, MPlist *plist); + +extern int mfont__has_char (MFrame *frame, MFont *font, MFont *spec, int c); + +extern unsigned mfont__encode_char (MFrame *frame, MFont *font, MFont *spec, + int c); + +extern int mfont__get_glyph_id (MFLTFont *font, MFLTGlyphString *gstring, + int from, int to); + +extern MFont *mfont__select (MFrame *frame, MFont *font, int max_size); + +extern MFontList *mfont__list (MFrame *frame, MFont *spec, MFont *request, + int limited_size); + +extern MRealizedFont *mfont__open (MFrame *frame, MFont *font, MFont *spec); + +extern void mfont__get_metric (MGlyphString *gstring, int from, int to); + +extern int mfont__get_metrics (MFLTFont *font, MFLTGlyphString *gstring, + int from, int to); + +extern void mfont__set_property (MFont *font, enum MFontProperty key, + MSymbol val); + +extern int mfont__split_name (char *name, int *property_idx, + unsigned short *point, unsigned short *resy); + +extern int mfont__parse_name_into_font (const char *name, MSymbol format, + MFont *font); + +extern MPlist *mfont__encoding_list (void); + +extern MFontCapability *mfont__get_capability (MSymbol sym); + +extern int mfont__check_capability (MRealizedFont *rfont, MSymbol capability); + +extern unsigned mfont__flt_encode_char (MSymbol layouter_name, int c); + +extern int mfont__flt_run (MGlyphString *gstring, int from, int to, + MRealizedFace *rface); + +#endif /* _M17N_FONT_H_ */ diff --git a/src/fontset.c b/src/fontset.c new file mode 100644 index 0000000..3c60aba --- /dev/null +++ b/src/fontset.c @@ -0,0 +1,1532 @@ +/* fontset.c -- fontset module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nFontset + @brief A fontset is an object that maps a character to fonts. + + A @e fontset is an object of the type @c MFontset. When drawing an + M-text, a fontset provides rules to select a font for each + character in the M-text according to the following information. + + @li The script character property of a character. + @li The language text property of a character. + @li The charset text property of a character. + + The documentation of mdraw_text () describes how that information is + used. */ + +/***ja @addtogroup m17nFontset + + @brief �ե���ȥ��åȤ�ʸ������ե���Ȥؤ��б��դ���Ԥ����֥������ȤǤ���. + + @e �ե���ȥ��å� �� @c MFontset ���Υ��֥������ȤǤ��롣M-text + ��ɽ���κݡ��ե���ȥ��åȤϰʲ��ξ�����Ѥ��� M-text + ��θġ���ʸ���ˤɤΥե���Ȥ��Ѥ��뤫���뵬§��Ϳ���롣 + + @li ʸ����ʸ���ץ��ѥƥ� "������ץ�" + @li ʸ���Υƥ����ȥץ��ѥƥ� "����" + @li ʸ���Υƥ����ȥץ��ѥƥ� "ʸ�����å�" + + �����ξ��󤬤ɤΤ褦���Ѥ����뤫�� mdraw_text () �������򻲾ȤΤ��ȡ� + + */ + +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include +#include + +#include "config.h" +#include "m17n-gui.h" +#include "m17n-misc.h" +#include "internal.h" +#include "symbol.h" +#include "plist.h" +#include "character.h" +#include "charset.h" +#include "internal-gui.h" +#include "font.h" +#include "fontset.h" + +static int mdebug_flag = MDEBUG_FONTSET; + +static M17NObjectArray fontset_table; + +struct MFontset +{ + M17NObject control; + + /* Name of the fontset. */ + MSymbol name; + + /* Initialized to 0, and incremented by one each time the fontset is + modified. */ + unsigned tick; + + /* Database from which to load the contents of the fontset. Once + loaded, this member is set to NULL. */ + MDatabase *mdb; + + /* SCRIPT vs PER-LANGUAGE (which is a plist LANGUAGE vs FONT-GROUP) */ + MPlist *per_script; + + /* CHARSET vs FONT-GROUP */ + MPlist *per_charset; + + /* FONT-GROUP */ + MPlist *fallback; +}; + +static MFontset *default_fontset; + +static MPlist *fontset_list; + +struct MRealizedFontset +{ + /* Fontset from which the realized fontset is realized. */ + MFontset *fontset; + + /* Initialized to ->tick. */ + unsigned tick; + + /* Font spec that must be satisfied, or NULL. */ + MFont *spec; + + /* Font spec requested by a face. */ + MFont request; + + /* The frame on which the realized fontset is realized. */ + MFrame *frame; + + MPlist *per_script; + + MPlist *per_charset; + + MPlist *fallback; +}; + + +static MPlist * +load_font_group (MPlist *plist, MPlist *elt) +{ + MPLIST_DO (elt, elt) + { + /* ELT ::= ( FONT-SPEC [ LAYOUTER ] ) ... */ + MPlist *elt2; + MFont *font; + MSymbol layouter_name; + + if (! MPLIST_PLIST_P (elt)) + MWARNING (MERROR_FONTSET); + elt2 = MPLIST_PLIST (elt); + if (! MPLIST_PLIST_P (elt2)) + MWARNING (MERROR_FONTSET); + MSTRUCT_CALLOC (font, MERROR_FONTSET); + mfont__set_spec_from_plist (font, MPLIST_PLIST (elt2)); + elt2 = MPLIST_NEXT (elt2); + layouter_name = Mt; + if (MPLIST_SYMBOL_P (elt2)) + layouter_name = MPLIST_SYMBOL (elt2); + if (layouter_name == Mnil) + layouter_name = Mt; + plist = mplist_add (plist, layouter_name, font); + continue; + warning: + /* ANSI-C requires some statement after a label. */ + continue; + } + return plist; +} + +/* Load FONTSET->per_script from the data in FONTSET->mdb. */ + +static void +load_fontset_contents (MFontset *fontset) +{ + MPlist *per_script, *per_charset, *font_group; + MPlist *fontset_def, *plist; + + fontset->per_script = per_script = mplist (); + fontset->per_charset = per_charset = mplist (); + fontset->fallback = mplist (); + if (! (fontset_def = (MPlist *) mdatabase_load (fontset->mdb))) + return; + + MPLIST_DO (plist, fontset_def) + { + /* PLIST ::= ( SCRIPT ( LANGUAGE ( FONT-SPEC [LAYOUTER]) ... ) ... ) + | ( CHARSET ( FONT-SPEC [LAYOUTER] ) ...) + | ( nil ( FONT-SPEC [LAYOUTER] ) ...) + FONT-SPEC :: = ( ... ) */ + MPlist *elt; + MSymbol sym; + + if (! MPLIST_PLIST_P (plist)) + MWARNING (MERROR_FONTSET); + elt = MPLIST_PLIST (plist); + if (! MPLIST_SYMBOL_P (elt)) + MWARNING (MERROR_FONTSET); + sym = MPLIST_SYMBOL (elt); + elt = MPLIST_NEXT (elt); + if (! MPLIST_PLIST_P (elt)) + MWARNING (MERROR_FONTSET); + if (sym == Mnil) + load_font_group (fontset->fallback, elt); + else if (MPLIST_PLIST_P (MPLIST_PLIST (elt))) + { + /* SYM is a charset. */ + font_group = mplist (); + per_charset = mplist_add (per_charset, sym, font_group); + load_font_group (font_group, elt); + } + else + { + /* SYM is a script */ + MPlist *per_lang = mplist (); + + per_script = mplist_add (per_script, sym, per_lang); + MPLIST_DO (elt, elt) + { + /* ELT ::= ( LANGUAGE FONT-DEF ...) ... */ + MPlist *elt2; + MSymbol lang; + + if (! MPLIST_PLIST_P (elt)) + MWARNING (MERROR_FONTSET); + elt2 = MPLIST_PLIST (elt); + if (! MPLIST_SYMBOL_P (elt2)) + MWARNING (MERROR_FONTSET); + lang = MPLIST_SYMBOL (elt2); + if (lang == Mnil) + lang = Mt; + font_group = mplist (); + mplist_add (per_lang, lang, font_group); + elt2 = MPLIST_NEXT (elt2); + load_font_group (font_group, elt2); + } + } + continue; + + warning: + /* ANSI-C requires some statement after a label. */ + continue; + } + + M17N_OBJECT_UNREF (fontset_def); + fontset->mdb = NULL; +} + +static void +free_fontset (void *object) +{ + MFontset *fontset = (MFontset *) object; + MPlist *plist, *pl, *p; + + if (fontset->per_script) + { + MPLIST_DO (plist, fontset->per_script) + { + MPLIST_DO (pl, MPLIST_PLIST (plist)) + { + MPLIST_DO (p, MPLIST_PLIST (pl)) + free (MPLIST_VAL (p)); + p = MPLIST_PLIST (pl); + M17N_OBJECT_UNREF (p); + } + pl = MPLIST_PLIST (plist); + M17N_OBJECT_UNREF (pl); + } + M17N_OBJECT_UNREF (fontset->per_script); + } + if (fontset->per_charset) + { + MPLIST_DO (pl, fontset->per_charset) + { + MPLIST_DO (p, MPLIST_PLIST (pl)) + free (MPLIST_VAL (p)); + p = MPLIST_PLIST (p); + M17N_OBJECT_UNREF (p); + } + M17N_OBJECT_UNREF (fontset->per_charset); + } + if (fontset->fallback) + { + MPLIST_DO (p, fontset->fallback) + free (MPLIST_VAL (p)); + M17N_OBJECT_UNREF (fontset->fallback); + } + + plist = mplist_find_by_key (fontset_list, fontset->name); + if (! plist) + mdebug_hook (); + mplist_pop (plist); + if (MPLIST_TAIL_P (fontset_list)) + { + M17N_OBJECT_UNREF (fontset_list); + fontset_list = NULL; + } + M17N_OBJECT_UNREGISTER (fontset_table, fontset); + free (object); +} + +static void +realize_fontset_elements (MFrame *frame, MRealizedFontset *realized) +{ + MFontset *fontset = realized->fontset; + MPlist *per_script, *per_charset, *font_group; + MPlist *plist, *p; + + realized->per_script = per_script = mplist (); + /* The actual elements of per_script are realized on demand. */ +#if 0 + MPLIST_DO (plist, fontset->per_script) + { + MPlist *pl; + + per_lang = mplist (); + per_script = mplist_add (per_script, MPLIST_KEY (plist), per_lang); + MPLIST_DO (pl, MPLIST_PLIST (plist)) + { + font_group = mplist (); + per_lang = mplist_add (per_lang, MPLIST_KEY (pl), font_group); + MPLIST_DO (p, MPLIST_PLIST (pl)) + font_group = mplist_add (font_group, + MPLIST_KEY (p), MPLIST_VAL (p)); + } + } +#endif + + realized->per_charset = per_charset = mplist (); + MPLIST_DO (plist, fontset->per_charset) + { + font_group = mplist (); + per_charset = mplist_add (per_charset, MPLIST_KEY (plist), font_group); + MPLIST_DO (p, MPLIST_PLIST (plist)) + font_group = mplist_add (font_group, MPLIST_KEY (p), MPLIST_VAL (p)); + } + realized->fallback = font_group = mplist (); + MPLIST_DO (p, fontset->fallback) + font_group = mplist_add (font_group, MPLIST_KEY (p), MPLIST_VAL (p)); +} + + +/* Return a plist of fonts for SCRIPT in FONTSET. The returned list + is acutally a plist of languages vs font groups (which is a plist). + If SCRIPT is nil, return a plist of fallback fonts. If FONTSET + doesn't record any fonts for SCRIPT, generate a proper font spec + lists for X backend and FreeType backend. */ + +MPlist * +get_per_script (MFontset *fontset, MSymbol script) +{ + MPlist *plist; + + if (script == Mnil) + return fontset->fallback; + plist = mplist_get (fontset->per_script, script); + if (! plist) + { + int len = MSYMBOL_NAMELEN (script); + char *cap = alloca (8 + len + 1); + MSymbol capability; + MFont *font; + MPlist *pl, *p; + + sprintf (cap, ":script=%s", MSYMBOL_NAME (script)); + capability = msymbol (cap); + + pl = mplist (); + MPLIST_DO (p, fontset->fallback) + { + font = mfont_copy (MPLIST_VAL (p)); + mfont_put_prop (font, Mregistry, Municode_bmp); + font->source = MFONT_SOURCE_FT; + font->capability = capability; + mplist_add (pl, Mt, font); + + font = mfont_copy (MPLIST_VAL (p)); + mfont_put_prop (font, Mregistry, Miso10646_1); + font->source = MFONT_SOURCE_X; + font->capability = capability; + mplist_add (pl, Mt, font); + } + plist = mplist (); + mplist_add (plist, Mt, pl); + mplist_add (fontset->per_script, script, plist); + } + return plist; +} + +static void +free_realized_fontset_elements (MRealizedFontset *realized) +{ + MPlist *plist, *pl, *p; + MFont *font; + MFontList *font_list; + + if (realized->per_script) + { + MPLIST_DO (plist, realized->per_script) + { + MPLIST_DO (pl, MPLIST_PLIST (plist)) + { + MPLIST_DO (p, MPLIST_PLIST (pl)) + { + font = MPLIST_VAL (p); + if (font->type == MFONT_TYPE_OBJECT) + { + font_list = (MFontList *) font; + free (font_list->fonts); + free (font_list); + } + /* This is to avoid freeing rfont again by the later + M17N_OBJECT_UNREF (p) */ + MPLIST_KEY (p) = Mt; + } + p = MPLIST_PLIST (pl); + M17N_OBJECT_UNREF (p); + } + pl = MPLIST_PLIST (plist); + M17N_OBJECT_UNREF (pl); + } + M17N_OBJECT_UNREF (realized->per_script); + } + if (realized->per_charset) + { + MPLIST_DO (plist, realized->per_charset) + { + MPLIST_DO (pl, MPLIST_PLIST (plist)) + { + font = MPLIST_VAL (pl); + if (font->type == MFONT_TYPE_OBJECT) + { + font_list = (MFontList *) font; + free (font_list->fonts); + free (font_list); + } + MPLIST_KEY (pl) = Mt; + } + pl = MPLIST_PLIST (plist); + M17N_OBJECT_UNREF (pl); + } + M17N_OBJECT_UNREF (realized->per_charset); + } + if (realized->fallback) + { + MPLIST_DO (plist, realized->fallback) + { + font = MPLIST_VAL (plist); + if (font->type == MFONT_TYPE_OBJECT) + { + font_list = (MFontList *) font; + free (font_list->fonts); + free (font_list); + } + MPLIST_KEY (plist) = Mt; + } + M17N_OBJECT_UNREF (realized->fallback); + } +} + +static void +update_fontset_elements (MRealizedFontset *realized) +{ + free_realized_fontset_elements (realized); + realize_fontset_elements (realized->frame, realized); +} + + + + +/* Internal API */ + +int +mfont__fontset_init () +{ + M17N_OBJECT_ADD_ARRAY (fontset_table, "Fontset"); + + Mfontset = msymbol ("fontset"); + Mfontset->managing_key = 1; + fontset_list = mplist (); + default_fontset = mfontset ("default"); + if (! default_fontset->mdb) + { + MFont font; + + MFONT_INIT (&font); + mfont_put_prop (&font, Mregistry, msymbol ("iso8859-1")); + mfontset_modify_entry (default_fontset, Mnil, Mnil, Mnil, + &font, Mnil, 1); + mfont_put_prop (&font, Mregistry, msymbol ("iso10646-1")); + mfontset_modify_entry (default_fontset, Mnil, Mnil, Mnil, + &font, Mnil, 1); + } + return 0; +} + + +void +mfont__fontset_fini () +{ + M17N_OBJECT_UNREF (default_fontset); + default_fontset = NULL; +} + + +MRealizedFontset * +mfont__realize_fontset (MFrame *frame, MFontset *fontset, + MFace *face, MFont *spec) +{ + MRealizedFontset *realized; + MFont request; + MPlist *plist; + + if (fontset->mdb) + load_fontset_contents (fontset); + + MFONT_INIT (&request); + mfont__set_spec_from_face (&request, face); + if (request.size <= 0) + { + mdebug_hook (); + request.size = 120; + } + MPLIST_DO (plist, frame->realized_fontset_list) + { + realized = (MRealizedFontset *) MPLIST_VAL (plist); + if (fontset->name == MPLIST_KEY (plist) + && ! memcmp (&request, &realized->request, sizeof (MFont)) + && (realized->spec + ? (spec && ! memcmp (spec, &realized->spec, sizeof (MFont))) + : ! spec)) + return realized; + } + + MSTRUCT_CALLOC (realized, MERROR_FONTSET); + realized->fontset = fontset; + M17N_OBJECT_REF (fontset); + realized->tick = fontset->tick; + if (spec) + { + MSTRUCT_CALLOC (realized->spec, MERROR_FONTSET); + *realized->spec = *spec; + } + realized->request = request; + realized->frame = frame; + realize_fontset_elements (frame, realized); + mplist_add (frame->realized_fontset_list, fontset->name, realized); + return realized; +} + + +void +mfont__free_realized_fontset (MRealizedFontset *realized) +{ + free_realized_fontset_elements (realized); + M17N_OBJECT_UNREF (realized->fontset); + if (realized->spec) + free (realized->spec); + free (realized); +} + + +static MRealizedFont * +try_font_list (MFrame *frame, MFontList *font_list, MFont *request, + MSymbol layouter, MGlyph *g, int *num, int all, int exact) +{ + int i, j; + MFont *font; + MRealizedFont *rfont; + + for (i = 0; i < font_list->nfonts; i++) + { + if (font_list->fonts[i].font->type == MFONT_TYPE_SPEC) + MFATAL (MERROR_FONT); + if (exact) + { + if (font_list->fonts[i].score > 0) + break; + } + else + { + if (font_list->fonts[i].score == 0) + continue; + } + font = font_list->fonts[i].font; + if (font->type == MFONT_TYPE_FAILURE) + continue; + /* Check if this font can display all glyphs. */ + for (j = 0; j < *num; j++) + { + int c = g[j].type == GLYPH_CHAR ? g[j].g.c : ' '; + MFLT *flt; + MCharTable *coverage; + + if (layouter != Mt + ? ((flt = mflt_get (layouter)) + ? (coverage = mflt_coverage (flt), + ! mchartable_lookup (coverage, c)) + : 0) + : ! mfont__has_char (frame, font, &font_list->object, c)) + break; + } + if (j == 0 && *num > 0) + continue; + if (j == *num || !all) + { + MCharTable *coverage = NULL; + + /* We found a font that can display the requested range of + glyphs. */ + if (font->type == MFONT_TYPE_REALIZED) + rfont = (MRealizedFont *) font; + else + { + rfont = mfont__open (frame, font, &font_list->object); + if (! rfont) + continue; + font_list->fonts[i].font = (MFont *) rfont; + } + rfont->layouter = layouter == Mt ? Mnil : layouter; + if (rfont->layouter) + { + MFLT *flt = mflt_get (rfont->layouter); + + if (flt) + coverage = mflt_coverage (flt); + } + *num = j; + for (j = 0; j < *num; j++) + { + int c = g[j].type == GLYPH_CHAR ? g[j].g.c : ' '; + + g[j].g.code = (coverage + ? (unsigned ) mchartable_lookup (coverage, c) + : mfont__encode_char (frame, (MFont *) rfont, + &font_list->object, c)); + } + return rfont; + } + } + return NULL; +} + + +static MRealizedFont * +try_font_group (MRealizedFontset *realized, MFont *request, + MPlist *font_group, MGlyph *g, int *num, int size) +{ + MFrame *frame = realized->frame; + MFont *font; + MFontList *font_list; + MRealizedFont *rfont; + MPlist *plist; + MSymbol layouter; + int best_score = -1, worst_score; + + for (plist = font_group; ! MPLIST_TAIL_P (plist); ) + { + int this_score; + + layouter = MPLIST_KEY (plist); + font = MPLIST_VAL (plist); + if (font->type == MFONT_TYPE_SPEC) + { + /* We have not yet made this entry a MFontList. */ + if (realized->spec) + { + MFont this = *font; + + if (mfont__merge (&this, realized->spec, 1) < 0) + { + mplist_pop (plist); + continue; + } + font_list = mfont__list (frame, &this, &this, size); + } + else + font_list = mfont__list (frame, font, request, size); + if (! font_list) + { + /* As there's no font matching this spec, remove this + element from the font group. */ + mplist_pop (plist); + continue; + } + MPLIST_VAL (plist) = font_list; + } + else + font_list = (MFontList *) font; + + this_score = font_list->fonts[0].score; + if ((this_score == 0) + && (rfont = try_font_list (frame, font_list, request, + layouter, g, num, 1, 1))) + return rfont; + if (best_score < 0) + { + best_score = worst_score = this_score; + plist = MPLIST_NEXT (plist); + } + else if (this_score >= worst_score) + { + worst_score = this_score; + plist = MPLIST_NEXT (plist); + } + else + { + MPlist *pl; + + MPLIST_DO (pl, font_group) + if (this_score < ((MFontList *) MPLIST_VAL (pl))->fonts[0].score) + break; + mplist_pop (plist); + mplist_push (pl, layouter, font_list); + } + } + + /* We couldn't find an exact matching font that can display all + glyphs. Find one that can at least display all glyphs. */ + MPLIST_DO (plist, font_group) + { + rfont = try_font_list (frame, MPLIST_VAL (plist), request, + MPLIST_KEY (plist), g, num, 1, 0); + if (rfont) + return rfont; + } + + /* We couldn't find a font that can display all glyphs. Find an + exact matching font that can at least display the first + glyph. */ + MPLIST_DO (plist, font_group) + { + rfont = try_font_list (frame, MPLIST_VAL (plist), request, + MPLIST_KEY (plist), g, num, 0, 1); + if (rfont) + return rfont; + } + + /* Find any font that can at least display the first glyph. */ + MPLIST_DO (plist, font_group) + { + rfont = try_font_list (frame, MPLIST_VAL (plist), request, + MPLIST_KEY (plist), g, num, 0, 0); + if (rfont) + return rfont; + } + + return NULL; +} + +MRealizedFont * +mfont__lookup_fontset (MRealizedFontset *realized, MGlyph *g, int *num, + MSymbol script, MSymbol language, MSymbol charset, + int size, int ignore_fallback) +{ + MCharset *preferred_charset = (charset == Mnil ? NULL : MCHARSET (charset)); + MPlist *per_charset, *per_script, *per_lang; + MPlist *plist; + MRealizedFont *rfont = NULL; + + if (MDEBUG_FLAG ()) + { + int i; + + MDEBUG_PRINT1 (" [FONTSET] fontset looking up for %s:", + script ? script->name : "none"); + for (i = 0; i < *num; i++) + MDEBUG_PRINT1 (" U+%04X", g[i].g.c); + MDEBUG_PRINT ("\n"); + } + + if (realized->tick != realized->fontset->tick) + update_fontset_elements (realized); + + if (preferred_charset + && (per_charset = mplist_get (realized->per_charset, charset)) != NULL + && (rfont = try_font_group (realized, &realized->request, per_charset, + g, num, size))) + goto done; + + if (script != Mnil) + { + MFont request = realized->request; + + if (script != Mlatin) + /* This is not appropriate for non-Latin scripts. */ + request.property[MFONT_REGISTRY] = 0; + + per_script = mplist_get (realized->per_script, script); + if (! per_script) + { + per_script = mplist_copy (get_per_script (realized->fontset, script)); + /* PER_SCRIPT ::= (LANGUAGE:(LAYOUTER:FONT-SPEC ...) ...) */ + MPLIST_DO (plist, per_script) + MPLIST_VAL (plist) = mplist_copy (MPLIST_VAL (plist)); + mplist_add (realized->per_script, script, per_script); + } + + /* We prefer font groups in this order: + (1) group matching with LANGUAGE if LANGUAGE is not Mnil + (2) group for generic language + (3) group not matching with LANGUAGE */ + if (language == Mnil) + language = Mt; + if ((per_lang = mplist_get (per_script, language)) + && (rfont = try_font_group (realized, &request, per_lang, + g, num, size))) + goto done; + + if (per_lang && *num > 1) + *num = 1; + if (language == Mt) + { + /* Try the above (3) */ + MPLIST_DO (plist, per_script) + if (MPLIST_KEY (plist) != language + && (rfont = try_font_group (realized, &request, + MPLIST_PLIST (plist), + g, num, size))) + goto done; + } + else + { + /* At first try the above (2) */ + if ((per_lang = mplist_get (per_script, Mt)) + && (rfont = try_font_group (realized, &request, per_lang, + g, num, size))) + goto done; + + if (per_lang && *num > 1) + *num = 1; + /* Then try the above (3) */ + MPLIST_DO (plist, per_script) + if (MPLIST_KEY (plist) != language + && MPLIST_KEY (plist) != Mt + && (rfont = try_font_group (realized, &request, + MPLIST_PLIST (plist), + g, num, size))) + goto done; + } + if (ignore_fallback) + goto done; + } + + if (language != Mnil) + /* Find a font group for this language from all scripts. */ + MPLIST_DO (plist, realized->per_script) + { + MFont request = realized->request; + + if (MPLIST_KEY (plist) != Mlatin) + request.property[MFONT_FOUNDRY] + = request.property[MFONT_FAMILY] + = request.property[MFONT_FAMILY] = 0; + if ((per_lang = mplist_get (MPLIST_PLIST (plist), language)) + && (rfont = try_font_group (realized, &request, per_lang, + g, num, size))) + goto done; + } + + /* Try fallback fonts. */ + rfont = try_font_group (realized, &realized->request, + realized->fallback, g, num, size); + done: + if (MDEBUG_FLAG ()) + { + if (rfont) + { + MSymbol family = mfont_get_prop (rfont->font, Mfamily); + MDEBUG_PRINT1 (" [FONTSET] found %s\n", family->name); + } + else + MDEBUG_PRINT (" [FONTSET] not found\n"); + } + + return rfont; +} + +MRealizedFont * +get_font_from_group (MFrame *frame, MPlist *plist, MFont *font) +{ + MRealizedFont *rfont; + + MPLIST_DO (plist, plist) + { + MFont spec = *(MFont *) MPLIST_VAL (plist); + if (mfont__merge (&spec, font, 1) < 0) + continue; + if (font->type == MFONT_TYPE_SPEC) + rfont = (MRealizedFont *) mfont_find (frame, &spec, NULL, 0); + else if (font->type == MFONT_TYPE_OBJECT) + rfont = mfont__open (frame, font, &spec); + else + rfont = (MRealizedFont *) font; + if (rfont + && (spec.capability == Mnil + || mfont__check_capability (rfont, spec.capability) == 0)) + { + rfont->layouter + = MPLIST_KEY (plist) == Mt ? Mnil : MPLIST_KEY (plist); + return rfont; + } + } + return NULL; +} + +MRealizedFont * +mfontset__get_font (MFrame *frame, MFontset *fontset, + MSymbol script, MSymbol language, MFont *font, + int *best) +{ + MPlist *per_script, *per_lang; + MRealizedFont *rfont; + + if (best) + *best = 0; + + if (language == Mnil) + language = Mt; + + if (script != Mnil) + { + per_script = get_per_script (fontset, script); + if ((per_lang = mplist_get (per_script, language)) + && (rfont = get_font_from_group (frame, per_lang, font))) + { + if (best) + *best = 1; + return rfont; + } + if (best) + *best = per_lang ? 0 : 1; + if (language == Mt) + { + MPLIST_DO (per_script, per_script) + if (MPLIST_KEY (per_script) != language + && (rfont = get_font_from_group (frame, + MPLIST_PLIST (per_script), + font))) + return rfont; + } + else + { + if ((per_lang = mplist_get (per_script, Mt)) + && (rfont = get_font_from_group (frame, per_lang, font))) + return rfont; + if (best) + *best = 0; + MPLIST_DO (per_script, per_script) + if (MPLIST_KEY (per_script) != language + && MPLIST_KEY (per_script) != Mt + && (rfont = get_font_from_group (frame, + MPLIST_PLIST (per_script), + font))) + return rfont; + } + } + + if (language != Mt) + MPLIST_DO (per_script, fontset->per_script) + { + if ((per_lang = mplist_get (MPLIST_PLIST (per_script), language)) + && (rfont = get_font_from_group (frame, per_lang, font))) + { + if (best) + *best = 1; + return rfont; + } + } + + if (best) + *best = 0; + if ((rfont = get_font_from_group (frame, fontset->fallback, font))) + return rfont; + return NULL; +} + + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/* External API */ + +/*** @addtogroup m17nFontset */ +/*** @{ */ + +/*=*/ +/***en + @brief Return a fontset. + + The mfontset () function returns a pointer to a fontset object of + name $NAME. If $NAME is @c NULL, it returns a pointer to the + default fontset. + + If no fontset has the name $NAME, a new one is created. At that + time, if there exists a data \<@c fontset, $NAME\> in the m17n + database, the fontset contents are initialized according to the + data. If no such data exists, the fontset contents are left + vacant. + + The macro M17N_INIT () creates the default fontset. An + application program can modify it before the first call of + mframe (). + + @return + This function returns a pointer to the found or newly created + fontset. */ +/***ja + @brief �ե���ȥ��åȤ��֤�. + + �ؿ� mfontset () ��̾�� $NAME ����ĥե���ȥ��åȥ��֥������ȤؤΥݥ��󥿤��֤��� + $NAME �� @c NULL �ʤ�С��ǥե���ȥե���ȥ��åȤؤΥݥ��󥿤��֤��� + + $NAME �Ȥ���̾������ĥե���ȥ��åȤ��ʤ���С���������Τ�����롣���κݡ� + m17n �ǡ����١����� \<@c fontset, $NAME\> + �Ȥ����ǡ���������С��ե���ȥ��åȤϤ��Υǡ����˱�äƽ��������롣 + �ʤ���С����Τޤޤˤ���롣 + + �ޥ��� M17N_INIT () �ϥǥե���ȤΥե���ȥ��åȤ��롣���ץꥱ�������ץ������� + mframe () ����ƸƤ֤ޤǤδ֤ϥǥե���ȥե���ȥ��åȤ��ѹ����뤳�Ȥ��Ǥ��롣 + + @return + ���δؿ��ϸ��Ĥ��ä������뤤�Ϻ�ä��ե���ȥ��åȤؤΥݥ��󥿤��֤��� + */ + +MFontset * +mfontset (char *name) +{ + MSymbol sym; + MFontset *fontset; + + if (! name) + { + fontset = default_fontset; + M17N_OBJECT_REF (fontset); + } + else + { + sym = msymbol (name); + fontset = mplist_get (fontset_list, sym); + if (fontset) + M17N_OBJECT_REF (fontset); + else + { + M17N_OBJECT (fontset, free_fontset, MERROR_FONTSET); + M17N_OBJECT_REGISTER (fontset_table, fontset); + fontset->name = sym; + fontset->mdb = mdatabase_find (Mfontset, sym, Mnil, Mnil); + if (! fontset->mdb) + { + fontset->per_script = mplist (); + fontset->per_charset = mplist (); + fontset->fallback = mplist (); + } + mplist_put (fontset_list, sym, fontset); + } + } + return fontset; +} + +/*=*/ + +/***en + @brief Return the name of a fontset. + + The mfontset_name () function returns the name of fontset $FONTSET. */ +/***ja + @brief �ե���ȥ��åȤ�̾�����֤�. + + �ؿ� mfontset_name () �ϥե���ȥ��å� $FONTSET ��̾�����֤��� */ +MSymbol +mfontset_name (MFontset *fontset) +{ + return fontset->name; +} + +/*=*/ + +/***en + @brief Make a copy of a fontset. + + The mfontset_copy () function makes a copy of fontset $FONTSET, gives it a + name $NAME, and returns a pointer to the created copy. $NAME must + not be a name of existing fontset. In such case, this function + returns NULL without making a copy. */ +/***ja + @brief �ե���ȥ��åȤΥ��ԡ�����. + + �ؿ� mfontset_copy () �ϥե���ȥ��å� $FONTSET �Υ��ԡ����äơ�̾�� + $NAME ��Ϳ�������Υ��ԡ��ؤΥݥ��󥿤��֤���$NAME + �ϴ�¸�Υե���ȥ��åȤ�̾���Ǥ��äƤϤʤ�ʤ������Τ褦�ʾ��ˤϥ��ԡ����餺�� + NULL ���֤��� */ + +MFontset * +mfontset_copy (MFontset *fontset, char *name) +{ + MSymbol sym = msymbol (name); + MFontset *copy = mplist_get (fontset_list, sym); + MPlist *plist, *pl, *p; + + if (copy) + return NULL; + M17N_OBJECT (copy, free_fontset, MERROR_FONTSET); + M17N_OBJECT_REGISTER (fontset_table, copy); + copy->name = sym; + + if (fontset->mdb) + load_fontset_contents (fontset); + + if (fontset->per_script) + { + copy->per_script = mplist (); + MPLIST_DO (plist, fontset->per_script) + { + MPlist *per_lang = mplist (); + + mplist_add (copy->per_script, MPLIST_KEY (plist), per_lang); + MPLIST_DO (pl, MPLIST_PLIST (plist)) + { + MPlist *font_group = mplist (); + + per_lang = mplist_add (per_lang, MPLIST_KEY (pl), font_group); + MPLIST_DO (p, MPLIST_PLIST (pl)) + font_group = mplist_add (font_group, MPLIST_KEY (p), + mfont_copy (MPLIST_VAL (p))); + } + } + } + if (fontset->per_charset) + { + MPlist *per_charset = mplist (); + + copy->per_charset = per_charset; + MPLIST_DO (pl, fontset->per_charset) + { + MPlist *font_group = mplist (); + + per_charset = mplist_add (per_charset, MPLIST_KEY (pl), font_group); + MPLIST_DO (p, MPLIST_PLIST (pl)) + font_group = mplist_add (font_group, MPLIST_KEY (p), + mfont_copy (MPLIST_VAL (p))); + } + } + if (fontset->fallback) + { + MPlist *font_group = mplist (); + + copy->fallback = font_group; + MPLIST_DO (p, fontset->fallback) + font_group = mplist_add (font_group, MPLIST_KEY (p), + mfont_copy (MPLIST_VAL (p))); + } + + mplist_put (fontset_list, sym, copy); + return copy; +} + +/*=*/ + +/***en + @brief Modify the contents of a fontset. + + The mfontset_modify_entry () function associates, in fontset + $FONTSET, a copy of $FONT with the $SCRIPT / $LANGUAGE pair or + with $CHARSET. + + Each font in a fontset is associated with a particular + script/language pair, with a particular charset, or with the + symbol @c Mnil. The fonts that are associated with the same item + make a group. + + If $SCRIPT is not @c Mnil, it must be a symbol identifying a + script. In this case, $LANGUAGE is either a symbol identifying a + language or @c Mnil, and $FONT is associated with the $SCRIPT / + $LANGUAGE pair. + + If $CHARSET is not @c Mnil, it must be a symbol representing a + charset object. In this case, $FONT is associated with that + charset. + + If both $SCRIPT and $CHARSET are not @c Mnil, two copies of $FONT + are created. Then one is associated with the $SCRIPT / $LANGUAGE + pair and the other with that charset. + + If both $SCRIPT and $CHARSET are @c Mnil, $FONT is associated with + @c Mnil. This kind of fonts are called @e fallback @e fonts. + + The argument $HOW specifies the priority of $FONT. If $HOW is + positive, $FONT has the highest priority in the group of fonts + that are associated with the same item. If $HOW is negative, + $FONT has the lowest priority. If $HOW is zero, $FONT becomes the + only available font for the associated item; all the other fonts + are removed from the group. + + If $LAYOUTER_NAME is not @c Mnil, it must be a symbol representing + a @ref mdbFLT (font layout table). In that case, if $FONT is + selected for drawing an M-text, that font layout table is used to + generate a glyph code sequence from a character sequence. + + @return + If the operation was successful, mfontset_modify_entry () returns 0. + Otherwise it returns -1 and assigns an error code to the external + variable #merror_code. */ + +/***ja + @brief �ե���ȥ��åȤ����Ƥ��ѹ�����. + + �ؿ� mfontset_modify_entry () �ϡ�$LANGUAGE �� $SCRIPT ���Ȥ߹�碌���ޤ��� + $CHARSET ���Ф��� $FONT �Υ��ԡ���Ȥ��褦�ˡ��ե���ȥ��å� $FONTSET �����ꤹ�롣 + + �ե���ȥ��å���γƥե���Ȥϡ�����Υ�����ץȤȸ���Υڥ��������ʸ�����åȡ�����ܥ� + @c Mnil �Τ����줫�ȴ�Ϣ�դ����Ƥ��롣Ʊ����Τȴ�Ϣ�դ���줿�ե���Ȥϥ��롼�פ������롣 + + $SCRIPT �� @c Mnil �Ǥ��뤫��������ץȤ����ꤹ�륷��ܥ�Ǥ��롣 + ����ܥ�Ǥ�����ˤϡ�$LANGUAGE �ϸ�������ꤹ�륷��ܥ뤫 @c + Mnil �Ǥ��ꡢ$FONT ��the $SCRIPT / $LANGUAGE �ڥ��˴�Ϣ�դ����롣 + + $CHARSET �� @c Mnil �Ǥ��뤫��ʸ�����åȥ��֥������Ȥ�ɽ������ܥ�Ǥ��롣 + ����ܥ�Ǥ�����ˤ� $FONT �Ϥ���ʸ�����åȤȴ�Ϣ�դ����롣 + + $SCRIPT �� $CHARSET �������� @c Mnil �Ǥʤ����ˤ� $FONT + �Υ��ԡ������ĺ��졢���줾�� $SCRIPT / $LANGUAGE + �ڥ���ʸ�����åȤ˴�Ϣ�դ����롣 + + $SCRIPT �� $CHARSET �������� @c Mnil �ʤ�С� $FONT �� @c Mnil + �ȴ�Ϣ�դ����롣���μ�Υե���Ȥ� @e fallback @e font �ȸƤФ�롣 + + ���� $HOW �� $FONT ��ͥ���٤���ꤹ�롣$HOW �����ʤ�С�$FONT + ��Ʊ����Τȴ�Ϣ�դ���줿���롼����Ǻǹ��ͥ���٤���ġ�$HOW + ����ʤ�С������ͥ���٤���ġ�$HOW �� 0 �ʤ�С�$FONT + �ϴ�Ϣ�դ���줿��Τ��Ф���ͣ������Ѳ�ǽ�ʥե���ȤȤʤꡢ¾�Υե���Ȥϥ��롼�פ����������롣 + + $LAYOUTER_NAME �� @c Mnil �Ǥ��뤫��@ref mdbFLT + �ʥե���ȥ쥤�����ȥơ��֥�ˤ򼨤�����ܥ�Ǥ��롣����ܥ�Ǥ���С�$FONT ���Ѥ��� + M-text ��ɽ������ݤˤϡ����Υե���ȥ쥤�����ȥơ��֥��Ȥä�ʸ���󤫤饰��ե���������������롣 + + @return + ���������������Ȥ���mfontset_modify_entry () �� 0 ���֤��� + ���Ԥ����Ȥ��� -1 ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_SYMBOL */ + +int +mfontset_modify_entry (MFontset *fontset, + MSymbol script, MSymbol language, MSymbol charset, + MFont *spec, MSymbol layouter_name, + int how) +{ + MPlist *per_lang, *plist[3]; + MFont *font = NULL; + int i; + + if (fontset->mdb) + load_fontset_contents (fontset); + + i = 0; + if (script != Mnil) + { + if (language == Mnil) + language = Mt; + per_lang = mplist_get (fontset->per_script, script); + if (! per_lang) + mplist_add (fontset->per_script, script, per_lang = mplist ()); + plist[i] = mplist_get (per_lang, language); + if (! plist[i]) + mplist_add (per_lang, language, plist[i] = mplist ()); + i++; + } + if (charset != Mnil) + { + plist[i] = mplist_get (fontset->per_charset, charset); + if (! plist[i]) + mplist_add (fontset->per_charset, charset, plist[i] = mplist ()); + i++; + } + if (script == Mnil && charset == Mnil) + { + plist[i++] = fontset->fallback; + } + + if (layouter_name == Mnil) + layouter_name = Mt; + for (i--; i >= 0; i--) + { + font = mfont_copy (spec); + font->type = MFONT_TYPE_SPEC; + if (how == 1) + mplist_push (plist[i], layouter_name, font); + else if (how == -1) + mplist_add (plist[i], layouter_name, font); + else + { + MPlist *pl; + + MPLIST_DO (pl, plist[i]) + free (MPLIST_VAL (pl)); + mplist_set (plist[i], Mnil, NULL); + mplist_add (plist[i], layouter_name, font); + } + } + + fontset->tick++; + return 0; +} + +/*=*/ + +/***en + @brief Lookup a fontset. + + The mfontset_lookup () function lookups $FONTSET and returns a + plist that describes the contents of $FONTSET corresponding to the + specified script, language, and charset. + + If $SCRIPT is @c Mt, keys of the returned plist are script name + symbols for which some fonts are specified and values are NULL. + + If $SCRIPT is a script name symbol, the returned plist is decided + by $LANGUAGE. + + @li If $LANGUAGE is @c Mt, keys of the plist are language name + symbols for which some fonts are specified and values are NULL. A + key may be @c Mt which means some fallback fonts are specified for + the script. + + @li If $LANGUAGE is a language name symbol, the plist is a @c + FONT-GROUP for the specified script and language. @c FONT-GROUP + is a plist whose keys are FLT (FontLayoutTable) name symbols (@c + Mt if no FLT is associated with the font) and values are pointers + to #MFont. + + @li If $LANGUAGE is @c Mnil, the plist is fallback @c FONT-GROUP + for the script. + + If $SCRIPT is @c Mnil, the returned plist is decided as below. + + @li If $CHARSET is @c Mt, keys of the returned plist are charset name + symbols for which some fonts are specified and values are NULL. + + @li If $CHARSET is a charset name symbol, the plist is a @c FONT-GROUP for + the charset. + + @li If $CHARSET is @c Mnil, the plist is a fallback @c FONT-GROUP. + + @return + It returns a plist describing the contents of a fontset. The + plist should be freed by m17n_object_unref (). */ +/***ja + @brief �ե���ȥ��åȤ򸡺�����. + + �ؿ� mfontset_lookup () �� $FONTSET �򸡺�����$FONTSET + �����ƤΤ������ꤷ��������ץȡ����졢ʸ�����åȤ��б�������ʬ��ɽ�� + plist ���֤��� + + $SCRIPT �� @c Mt �ʤ�С��֤� plist + �Υ����ϥե���Ȥ����ꤵ��Ƥ��륹����ץ�̾�Υ���ܥ�Ǥ��ꡢ�ͤ� + NULL �Ǥ��롣 + + $SCRIPT ��������ץ�̾�Υ���ܥ�Ǥ���С��֤� + plist �� $LANGUAGE�ˤ�ä���ޤ롣 + + @li $LANGUAGE �� @c Mt �ʤ�С�plist + �Υ����ϥե���Ȥ����ꤵ��Ƥ������̾�Υ���ܥ�Ǥ��ꡢ�ͤ� + NULL �Ǥ��롣������ @c Mt + �Ǥ��뤳�Ȥ⤢�ꡢ���ξ�礽�Υ�����ץȤ˥ե�����Хå��ե���Ȥ����뤳�Ȥ��̣���롣 + + @li $LANGUAGE ������̾�Υ���ܥ�ʤ�С�plist �ϻ���Υ�����ץȤȸ�����Ф��� + @c FONT-GROUP �Ǥ��롣@c FONT-GROUP �Ȥϡ������� FLT + (FontLayoutTable) ̾�Υ���ܥ�Ǥ��ꡢ�ͤ� #MFont + �ؤΥݥ��󥿤Ǥ���褦�� plist �Ǥ��롣�������ե���Ȥ� FLT + ���б��դ����Ƥ��ʤ����ˤϡ������� @c Mt �ˤʤ롣 + + @li $LANGUAGE �� @c Mnil �ʤ�С�plist �Ϥ��Υ�����ץ��ѤΥե�����Хå� + @c FONT-GROUP �Ǥ��롣 + + $SCRIPT �� @c Mnil �ʤ�С��֤� plist �ϰʲ��Τ褦����ޤ롣 + + @li $CHARSET �� @c Mt �ʤ�С�plist + �Υ����ϥե���Ȥ����ꤵ��Ƥ���ʸ�����å�̾�Υ���ܥ�Ǥ��ꡢ�ͤ� + NULL �Ǥ��롣 + + @li $CHARSET ��ʸ�����å�̾�Υ���ܥ�ʤ�С�plist �Ϥ���ʸ�����å��Ѥ� + @c FONT-GROUP �Ǥ��롣 + + @li $CHARSET �� @c Mnil �ʤ�С�plist �ϥե�����Хå� @c FONT-GROUP �Ǥ��롣 + + @return + ���δؿ��ϥե���ȥ��åȤ����Ƥ�ɽ�� plist ���֤��� + plist �� m17n_object_unref () �Dz��������٤��Ǥ��롣 */ + +MPlist * +mfontset_lookup (MFontset *fontset, + MSymbol script, MSymbol language, MSymbol charset) +{ + MPlist *plist = mplist (), *pl, *p; + + if (fontset->mdb) + load_fontset_contents (fontset); + if (script == Mt) + { + if (! fontset->per_script) + return plist; + p = plist; + MPLIST_DO (pl, fontset->per_script) + p = mplist_add (p, MPLIST_KEY (pl), NULL); + return plist; + } + if (script != Mnil) + { + pl = get_per_script (fontset, script); + if (MPLIST_TAIL_P (pl)) + return plist; + if (language == Mt) + { + p = plist; + MPLIST_DO (pl, pl) + p = mplist_add (p, MPLIST_KEY (pl), NULL); + return plist; + } + if (language == Mnil) + language = Mt; + pl = mplist_get (pl, language); + } + else if (charset != Mnil) + { + if (! fontset->per_charset) + return plist; + if (charset == Mt) + { + p = plist; + MPLIST_DO (pl, fontset->per_charset) + p = mplist_add (p, MPLIST_KEY (pl), NULL); + return plist; + } + pl = mplist_get (fontset->per_charset, charset); + } + else + pl = fontset->fallback; + if (! pl) + return plist; + return mplist_copy (pl); +} + + +/*** @} */ + +/*** @addtogroup m17nDebug */ +/*=*/ +/*** @{ */ + +/***en + @brief Dump a fontset. + + The mdebug_dump_fontset () function prints fontset $FONTSET in a + human readable way to the stderr or to what specified by the + environment variable MDEBUG_OUTPUT_FILE. $INDENT specifies how + many columns to indent the lines but the first one. + + @return + This function returns $FONTSET. */ +/***ja + @brief �ե���ȥ��åȤ����פ���. + + �ؿ� mdebug_dump_face () �ϥե���ȥ��å� $FONTSET ��ɸ�२�顼���� + �⤷���ϴĶ��ѿ� MDEBUG_DUMP_FONT �ǻ��ꤵ�줿�ե�����˿ʹ֤˲��� + �ʷ��ǽ��Ϥ��롣 $INDENT �ϣ����ܰʹߤΥ���ǥ�Ȥ���ꤹ�롣 + + @return + ���δؿ��� $FONTSET ���֤��� */ + +MFontset * +mdebug_dump_fontset (MFontset *fontset, int indent) +{ + char *prefix = (char *) alloca (indent + 1); + MPlist *plist, *pl, *p; + + memset (prefix, 32, indent); + prefix[indent] = 0; + + fprintf (mdebug__output, "(fontset %s", fontset->name->name); + if (fontset->per_script) + MPLIST_DO (plist, fontset->per_script) + { + fprintf (mdebug__output, "\n %s(%s", prefix, MPLIST_KEY (plist)->name); + MPLIST_DO (pl, MPLIST_PLIST (plist)) + { + fprintf (mdebug__output, "\n %s(%s", prefix, + MPLIST_KEY (pl)->name); + MPLIST_DO (p, MPLIST_PLIST (pl)) + { + fprintf (mdebug__output, "\n %s(0x%X %s ", prefix, + (unsigned) MPLIST_VAL (p), + MPLIST_KEY (p)->name); + mdebug_dump_font (MPLIST_VAL (p)); + fprintf (mdebug__output, ")"); + } + fprintf (mdebug__output, ")"); + } + fprintf (mdebug__output, ")"); + } + if (fontset->per_charset) + MPLIST_DO (pl, fontset->per_charset) + { + fprintf (mdebug__output, "\n %s(%s", prefix, MPLIST_KEY (pl)->name); + MPLIST_DO (p, MPLIST_PLIST (pl)) + { + fprintf (mdebug__output, "\n %s(%s ", prefix, + MPLIST_KEY (p)->name); + mdebug_dump_font (MPLIST_VAL (p)); + fprintf (mdebug__output, ")"); + } + fprintf (mdebug__output, ")"); + } + + if (fontset->fallback) + MPLIST_DO (p, fontset->fallback) + { + fprintf (mdebug__output, "\n %s(%s ", prefix, MPLIST_KEY (p)->name); + mdebug_dump_font (MPLIST_VAL (p)); + fprintf (mdebug__output, ")"); + } + + fprintf (mdebug__output, ")"); + return fontset; +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/fontset.h b/src/fontset.h new file mode 100644 index 0000000..da30f04 --- /dev/null +++ b/src/fontset.h @@ -0,0 +1,43 @@ +/* fontset.h -- header file for the fontset module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_FONTSET_H_ +#define _M17N_FONTSET_H_ + +extern MRealizedFontset *mfont__realize_fontset (MFrame *frame, + MFontset *fontset, + MFace *face, MFont *spec); + +void mfont__free_realized_fontset (MRealizedFontset *realized); + +extern MRealizedFont *mfont__lookup_fontset (MRealizedFontset *realized, + MGlyph *g, int *num, + MSymbol script, MSymbol language, + MSymbol charset, int size, + int ignore_fallback); + +extern MRealizedFont *mfontset__get_font (MFrame *frame, MFontset *fontset, + MSymbol script, MSymbol language, + MFont *font, int *best); + + +#endif /* _M17N_FONTSET_H_ */ diff --git a/src/input-gui.c b/src/input-gui.c new file mode 100644 index 0000000..8018d49 --- /dev/null +++ b/src/input-gui.c @@ -0,0 +1,764 @@ +/* input-gui.c -- gui-based input method module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nInputMethodWin + @brief Input method support on window systems. + + The input driver @c minput_gui_driver is provided for internal + input methods that is useful on window systems. It displays + preedit text and status text at the inputting spot. See the + documentation of @c minput_gui_driver for more details. + + In the m17n-X library, the foreign input method of name @c Mxim is + provided. It uses XIM (X Input Method) as a background input + engine. The symbol @c Mxim has a property @c Minput_driver whose + value is a pointer to the input driver @c minput_xim_driver. See + the documentation of @c minput_xim_driver for more details. */ + +/***ja + @addtogroup m17nInputMethodWin + @brief ������ɥ������ƥ������ϥ᥽�åɤΥ��ݡ���. + + ���ϥɥ饤�� @c minput_gui_driver �ϡ� + ������ɥ������ƥ����Ѥ������������ϥ᥽�å��ѤΥɥ饤�ФǤ��롣 + ���Υɥ饤�Ф����ϥ��ݥåȤ� preedit �ƥ����Ȥ� status + �ƥ����Ȥ�ɽ�����롣�ܺ٤ˤĤ��Ƥ� @c minput_gui_driver �������򻲾ȤΤ��ȡ� + + m17n-X �饤�֥��ϡ�@c Mxim �ȸ���̾������ij������ϥ᥽�åɤ��󶡤��Ƥ��롣����� + XIM (X Input Method) ��Хå����饦��ɤ����ϥ��󥸥�Ȥ������Ѥ��롣����ܥ� + @c Mxim �� @c Minput_driver �Ȥ����ץ��ѥƥ�����äƤ��ꡢ�����ͤ����ϥɥ饤�� + @c minput_xim_driver �ؤΥݥ��󥿤Ǥ��롣 �ܺ٤ˤĤ��Ƥ� + @c minput_xim_driver �������򻲾ȤΤ��ȡ� */ + +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include + +#include "config.h" +#include "m17n-gui.h" +#include "m17n-misc.h" +#include "internal.h" +#include "internal-gui.h" +#include "input.h" + +typedef struct +{ + MDrawWindow win; + MDrawMetric geometry; + MDrawControl control; + int mapped; +} MInputGUIWinInfo; + +typedef struct +{ + MInputContextInfo *ic_info; + + MFrame *frame; + /* .x and .y are not used. */ + MInputGUIWinInfo client; + /* In the following members, is relative to . */ + MInputGUIWinInfo focus; + MInputGUIWinInfo preedit; + MInputGUIWinInfo status; + MInputGUIWinInfo candidates; +} MInputGUIContextInfo; + +static MFace *status_face; +static MFaceBoxProp face_box_prop; + +static int +win_create_ic (MInputContext *ic) +{ + MInputGUIContextInfo *win_ic_info; + MInputGUIArgIC *win_info = (MInputGUIArgIC *) ic->arg; + MFrame *frame = win_info->frame; + + if ((*minput_default_driver.create_ic) (ic) < 0) + return -1; + + MSTRUCT_CALLOC (win_ic_info, MERROR_IM); + win_ic_info->ic_info = (MInputContextInfo *) ic->info; + win_ic_info->frame = frame; + win_ic_info->client.win = win_info->client; + (*frame->driver->window_geometry) (frame, win_info->client, win_info->client, + &win_ic_info->client.geometry); + win_ic_info->focus.win = win_info->focus; + (*frame->driver->window_geometry) (frame, win_info->focus, win_info->client, + &win_ic_info->focus.geometry); + + win_ic_info->preedit.win = (*frame->driver->create_window) (frame, win_info->client); + win_ic_info->preedit.control.two_dimensional = 1; + win_ic_info->preedit.control.as_image = 0; + win_ic_info->preedit.control.with_cursor = 1; + win_ic_info->preedit.control.cursor_width = 1; + win_ic_info->preedit.control.enable_bidi = 1; + win_ic_info->preedit.geometry.x = -1; + win_ic_info->preedit.geometry.y = -1; + + win_ic_info->status.win = (*frame->driver->create_window) (frame, win_info->client); + win_ic_info->status.control.as_image = 1; + win_ic_info->status.control.enable_bidi = 1; + + win_ic_info->candidates.win = (*frame->driver->create_window) (frame, win_info->client); + win_ic_info->candidates.control.as_image = 1; + + ic->info = win_ic_info; + + return 0; +} + +static void +win_destroy_ic (MInputContext *ic) +{ + MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info; + MInputContextInfo *ic_info = (MInputContextInfo *) win_ic_info->ic_info; + MFrame *frame = win_ic_info->frame; + + (*frame->driver->destroy_window) (frame, win_ic_info->preedit.win); + (*frame->driver->destroy_window) (frame, win_ic_info->status.win); + (*frame->driver->destroy_window) (frame, win_ic_info->candidates.win); + ic->info = ic_info; + (*minput_default_driver.destroy_ic) (ic); + free (win_ic_info); +} + +static int +win_filter (MInputContext *ic, MSymbol key, void *arg) +{ + MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info; + int ret; + + if (! ic + || ! ic->active) + return 0; + + if (key == Mnil && arg) + { + key = minput_event_to_key (win_ic_info->frame, arg); + if (key == Mnil) + return 1; + } + ic->info = win_ic_info->ic_info; + ret = (*minput_default_driver.filter) (ic, key, arg); + win_ic_info->ic_info = (MInputContextInfo *) ic->info; + ic->info = win_ic_info; + return ret; +} + +static void +adjust_window_and_draw (MFrame *frame, MInputContext *ic, MText *mt, int type) +{ + MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info; + MDrawControl *control; + MDrawWindow win; + MDrawMetric *geometry, physical, logical; + int xoff = win_ic_info->focus.geometry.x; + int yoff = win_ic_info->focus.geometry.y; + int x0, x1, y0, y1; + int len = mtext_nchars (mt); + + if (type == 0) + { + win = win_ic_info->preedit.win; + control = &win_ic_info->preedit.control; + geometry = &win_ic_info->preedit.geometry; + len++; + } + else if (type == 1) + { + win = win_ic_info->status.win; + control = &win_ic_info->status.control; + geometry = &win_ic_info->status.geometry; + } + else + { + win = win_ic_info->candidates.win; + control = &win_ic_info->candidates.control; + geometry = &win_ic_info->candidates.geometry; + } + + mdraw_text_extents (frame, mt, 0, len, control, &physical, &logical, NULL); + x0 = physical.x, x1 = x0 + physical.width; + y0 = physical.y, y1 = y0 + physical.height; + if (x0 > logical.x) + x0 = logical.x; + if (x1 < logical.x + logical.width) + x1 = logical.x + logical.width; + if (y0 > logical.y) + y0 = logical.y; + if (y1 < logical.y + logical.height) + y1 = logical.y + logical.height; + physical.width = x1 - x0; + physical.height = y1 - y0; + physical.x = xoff + ic->spot.x; + if (physical.x + physical.width > win_ic_info->client.geometry.width) + physical.x = win_ic_info->client.geometry.width - physical.width; + if (type == 0) + { + if (len <= 1) + { + physical.height = physical.width = 1; + physical.x = physical.y = -1; + } + else + { + if (y0 > - ic->spot.ascent) + { + physical.height += y0 + ic->spot.ascent; + y0 = - ic->spot.ascent; + } + if (y1 < ic->spot.descent) + { + physical.height += ic->spot.descent - y1; + } + physical.y = yoff + ic->spot.y + y0; + } + } + else if (type == 1) + { + physical.y = yoff + ic->spot.y + ic->spot.descent + 2; + if (physical.y + physical.height > win_ic_info->client.geometry.height + && yoff + ic->spot.y - ic->spot.ascent - 2 - physical.height >= 0) + physical.y = yoff + ic->spot.y - ic->spot.ascent - 2 - physical.height; + } + else + { + if (win_ic_info->status.mapped) + { + /* We assume that status is already drawn. */ + if (win_ic_info->status.geometry.y < yoff + ic->spot.y) + /* As there was no lower room for status, candidates must also + be drawn upper. */ + physical.y = win_ic_info->status.geometry.y - 1 - physical.height; + else + { + /* There was a lower room for status. */ + physical.y = (win_ic_info->status.geometry.y + + win_ic_info->status.geometry.height + + 1); + if (physical.y + physical.height + > win_ic_info->client.geometry.height) + /* But not for candidates. */ + physical.y = (yoff + ic->spot.y - ic->spot.ascent - 1 + - physical.height); + } + } + else + { + physical.y = yoff + ic->spot.y + ic->spot.descent + 2; + if ((physical.y + physical.height + > win_ic_info->client.geometry.height) + && (yoff + ic->spot.y - ic->spot.ascent - 2 - physical.height + >= 0)) + physical.y = (yoff + ic->spot.y - ic->spot.ascent - 2 + - physical.height); + } + } + + (*frame->driver->adjust_window) (frame, win, geometry, &physical); + mdraw_text_with_control (frame, win, -x0, -y0, mt, 0, len, control); +} + +static void +win_callback (MInputContext *ic, MSymbol command) +{ + MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info; + MFrame *frame = win_ic_info->frame; + + if (command == Minput_preedit_draw) + { + MText *mt; + MFace *face = mface (); + + if (! win_ic_info->preedit.mapped) + { + (*frame->driver->map_window) (frame, win_ic_info->preedit.win); + win_ic_info->preedit.mapped = 1; + } + win_ic_info->preedit.control.cursor_pos = ic->cursor_pos; + if (ic->spot.fontsize) + mface_put_prop (face, Msize, (void *) ic->spot.fontsize); + mface_merge (face, mface_underline); + mtext_push_prop (ic->preedit, 0, mtext_nchars (ic->preedit), + Mface, face); + M17N_OBJECT_UNREF (face); + if (ic->im->language != Mnil) + mtext_put_prop (ic->preedit, 0, mtext_nchars (ic->preedit), Mlanguage, + ic->im->language); + if (ic->candidate_list && ic->candidate_show) + mtext_push_prop (ic->preedit, ic->candidate_from, ic->candidate_to, + Mface, mface_reverse_video); + if (mtext_nchars (ic->produced) == 0) + mt = ic->preedit; + else + { + mt = mtext_dup (ic->produced); + mtext_cat (mt, ic->preedit); + win_ic_info->preedit.control.cursor_pos + += mtext_nchars (ic->produced); + } + adjust_window_and_draw (frame, ic, mt, 0); + if (ic->candidate_list) + mtext_pop_prop (ic->preedit, 0, mtext_nchars (ic->preedit), Mface); + mtext_pop_prop (ic->preedit, 0, mtext_nchars (ic->preedit), Mface); + if (mtext_nchars (ic->produced) != 0) + M17N_OBJECT_UNREF (mt); + } + else if (command == Minput_status_draw) + { + if (! win_ic_info->client.win) + return; + mtext_put_prop (ic->status, 0, mtext_nchars (ic->status), Mface, + status_face); + if (ic->im->language != Mnil) + mtext_put_prop (ic->status, 0, mtext_nchars (ic->status), Mlanguage, + ic->im->language); + adjust_window_and_draw (frame, ic, ic->status, 1); + } + else if (command == Minput_candidates_draw) + { + MPlist *group; + MText *mt; + int i, len; + int from, to; + + if (! ic->candidate_list || ! ic->candidate_show) + { + if (win_ic_info->candidates.mapped) + { + (*frame->driver->unmap_window) (frame, win_ic_info->candidates.win); + win_ic_info->candidates.mapped = 0; + } + return; + } + + if (! win_ic_info->candidates.mapped) + { + (*frame->driver->map_window) (frame, win_ic_info->candidates.win); + win_ic_info->candidates.mapped = 1; + } + + i = 0; + group = ic->candidate_list; + while (1) + { + if (mplist_key (group) == Mtext) + len = mtext_len (mplist_value (group)); + else + len = mplist_length (mplist_value (group)); + if (i + len > ic->candidate_index) + break; + i += len; + group = mplist_next (group); + } + + mt = mtext (); + if (mplist_key (group) == Mtext) + { + MText *candidates = (MText *) mplist_value (group); + + from = (ic->candidate_index - i) * 2 + 1; + to = from + 1; + for (i = 0; i < len; i++) + { + mtext_cat_char (mt, ' '); + mtext_cat_char (mt, mtext_ref_char (candidates, i)); + } + } + else + { + MPlist *pl; + + for (pl = (MPlist *) mplist_value (group); + i < ic->candidate_index && mplist_key (pl) != Mnil; + i++, pl = mplist_next (pl)) + { + mtext_cat_char (mt, ' '); + mtext_cat (mt, (MText *) mplist_value (pl)); + } + from = mtext_nchars (mt) + 1; + to = from + mtext_nchars ((MText *) mplist_value (pl)); + for (; mplist_key (pl) != Mnil; pl = mplist_next (pl)) + { + mtext_cat_char (mt, ' '); + mtext_cat (mt, (MText *) mplist_value (pl)); + } + } + mtext_cat_char (mt, ' '); + mtext_push_prop (mt, 0, mtext_nchars (mt), Mface, status_face); + mtext_push_prop (mt, from, to, Mface, mface_reverse_video); + if (ic->im->language != Mnil) + mtext_put_prop (mt, 0, mtext_nchars (mt), Mlanguage, ic->im->language); + adjust_window_and_draw (frame, ic, mt, 2); + M17N_OBJECT_UNREF (mt); + } + else if (command == Minput_set_spot) + { + minput_callback (ic, Minput_preedit_draw); + minput_callback (ic, Minput_status_draw); + minput_callback (ic, Minput_candidates_draw); + } + else if (command == Minput_toggle) + { + if (ic->active) + { + minput_callback (ic, Minput_preedit_done); + minput_callback (ic, Minput_status_done); + minput_callback (ic, Minput_candidates_done); + } + else + { + minput_callback (ic, Minput_preedit_start); + minput_callback (ic, Minput_status_start); + minput_callback (ic, Minput_candidates_start); + } + } + else if (command == Minput_preedit_start) + { + } + else if (command == Minput_preedit_done) + { + if (win_ic_info->preedit.mapped) + { + (*frame->driver->unmap_window) (frame, win_ic_info->preedit.win); + win_ic_info->preedit.mapped = 0; + } + } + else if (command == Minput_status_start) + { + if (! win_ic_info->status.mapped) + { + (*frame->driver->map_window) (frame, win_ic_info->status.win); + win_ic_info->status.mapped = 1; + } + } + else if (command == Minput_status_done) + { + if (win_ic_info->status.mapped) + { + (*frame->driver->unmap_window) (frame, win_ic_info->status.win); + win_ic_info->status.mapped = 0; + } + } + else if (command == Minput_candidates_start) + { + if (! win_ic_info->candidates.mapped) + { + (*frame->driver->map_window) (frame, win_ic_info->candidates.win); + win_ic_info->candidates.mapped = 1; + } + } + else if (command == Minput_candidates_done) + { + if (win_ic_info->candidates.mapped) + { + (*frame->driver->unmap_window) (frame, win_ic_info->candidates.win); + win_ic_info->candidates.mapped = 0; + } + } + else if (command == Minput_reset) + { + MInputCallbackFunc func; + + if (minput_default_driver.callback_list + && (func = ((MInputCallbackFunc) + mplist_get_func (minput_default_driver.callback_list, + Minput_reset)))) + { + MInputContextInfo *ic_info + = (MInputContextInfo *) win_ic_info->ic_info; + ic->info = ic_info; + (func) (ic, Minput_reset); + ic->info = win_ic_info; + } + if (ic->preedit_changed) + minput_callback (ic, Minput_preedit_draw); + if (ic->status_changed) + minput_callback (ic, Minput_status_draw); + if (ic->candidates_changed) + minput_callback (ic, Minput_candidates_draw); + } +} + +static int +win_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt) +{ + MInputGUIContextInfo *win_ic_info = (MInputGUIContextInfo *) ic->info; + MInputContextInfo *ic_info = (MInputContextInfo *) win_ic_info->ic_info; + int ret; + + ic->info = ic_info; + ret = (*minput_default_driver.lookup) (ic, key, arg, mt); + ic->info = win_ic_info; + return ret; +} + + + +int +minput__win_init () +{ + minput_gui_driver = minput_default_driver; + + minput_gui_driver.create_ic = win_create_ic; + minput_gui_driver.destroy_ic = win_destroy_ic; + minput_gui_driver.filter = win_filter; + minput_gui_driver.lookup = win_lookup; + { + MPlist *plist = mplist (); + + minput_gui_driver.callback_list = plist; + mplist_put_func (plist, Minput_preedit_start, M17N_FUNC (win_callback)); + mplist_put_func (plist, Minput_preedit_draw, M17N_FUNC (win_callback)); + mplist_put_func (plist, Minput_preedit_done, M17N_FUNC (win_callback)); + mplist_put_func (plist, Minput_status_start, M17N_FUNC (win_callback)); + mplist_put_func (plist, Minput_status_draw, M17N_FUNC (win_callback)); + mplist_put_func (plist, Minput_status_done, M17N_FUNC (win_callback)); + mplist_put_func (plist, Minput_candidates_start, M17N_FUNC (win_callback)); + mplist_put_func (plist, Minput_candidates_draw, M17N_FUNC (win_callback)); + mplist_put_func (plist, Minput_candidates_done, M17N_FUNC (win_callback)); + mplist_put_func (plist, Minput_set_spot, M17N_FUNC (win_callback)); + mplist_put_func (plist, Minput_toggle, M17N_FUNC (win_callback)); + mplist_put_func (plist, Minput_reset, M17N_FUNC (win_callback)); + } +#if 0 + /* This will make the caller of minput_method_open() pazzled. */ + minput_driver = &minput_gui_driver; +#endif + + face_box_prop.width = 1; + face_box_prop.color_top = face_box_prop.color_left + = face_box_prop.color_bottom = face_box_prop.color_right + = msymbol ("black"); + face_box_prop.inner_hmargin = face_box_prop.inner_vmargin = 2; + face_box_prop.outer_hmargin = face_box_prop.outer_vmargin = 1; + status_face = mface (); + mface_put_prop (status_face, Mbox, &face_box_prop); + + return 0; +} + +void +minput__win_fini () +{ + M17N_OBJECT_UNREF (status_face); + if (minput_gui_driver.callback_list) + { + M17N_OBJECT_UNREF (minput_gui_driver.callback_list); + minput_gui_driver.callback_list = NULL; + } +} + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/* External API */ + +/*** @addtogroup m17nInputMethodWin */ +/*** @{ */ + +/*=*/ +/***en + @brief Input driver for internal input methods on window systems. + + The input driver @c minput_gui_driver is for internal input + methods to be used on window systems. + + It creates sub-windows for a preedit text and a status text, and + displays them at the input spot set by the function + minput_set_spot (). + + The macro M17N_INIT () set the variable @c minput_driver to the + pointer to this driver so that all internal input methods use it. + + Therefore, unless @c minput_driver is changed from the default, + the driver dependent arguments to the functions whose name begin + with minput_ must are treated as follows. + + The argument $ARG of the function minput_open_im () is ignored. + + The argument $ARG of the function minput_create_ic () must be a + pointer to the structure @c MInputGUIArgIC. See the documentation + of @c MInputGUIArgIC for more details. + + If the argument $KEY of function minput_filter () is @c Mnil, the + argument $ARG must be a pointer to the object of type @c XEvent. + In that case, $KEY is generated from $ARG. + + The argument $ARG of the function minput_lookup () must be the + same one as that of the function minput_filter (). */ + +/***ja + @brief ������ɥ������ƥ���������ϥ᥽�å������ϥɥ饤��. + + ���ϥɥ饤�� @c minput_gui_driver + �ϡ�������ɥ������ƥ����Ѥ��������ϥ᥽�å��ѥɥ饤�ФǤ��롣 + + ���Υɥ饤�Фϡ��ؿ� minput_set_spot () �ˤ�ä����ꤵ�줿���ϥ��ݥåȤ� + preedit �ƥ������ѤΥ��֥�����ɥ��� status + �ƥ������ѤΥ��֥�����ɥ����ꡢ���줾���ɽ�����롣 + + �ޥ��� M17N_INIT () ���ѿ� @c minput_driver + �򤳤Υɥ饤�ФؤΥݥ��󥿤����ꤷ�����Ƥ��������ϥ᥽�åɤ����Υɥ饤�Ф�Ȥ��褦�ˤ��롣 + + �������äơ�@c minput_driver ���ǥե�����ͤΤޤޤǤ���С�minput_ + �ǻϤޤ�̾������Ĵؿ��ΰ����Τ����ɥ饤�а�¸�Τ�Τϰʲ��Τ褦�ˤʤ롣 + + �ؿ� minput_open_im () �ΰ��� $ARG ��̵�뤵��롣 + + �ؿ� minput_create_ic () �ΰ��� $ARG �Ϲ�¤�� @c MInputGUIArgIC + �ؤΥݥ��󥿤Ǥʤ��ƤϤʤ�ʤ����ܺ٤ˤĤ��Ƥ� @c MInputGUIArgIC + �������򻲾ȤΤ��ȡ� + + �ؿ� minput_filter () �ΰ��� $ARG �� @c Mnil �ξ�硢 $ARG �� @c + XEvent ���Υ��֥������ȤؤΥݥ��󥿤Ǥʤ��ƤϤʤ�ʤ������ξ�� + $KEY �� $ARG ������������롣 + + �ؿ� minput_lookup () �ΰ��� $ARG �ϴؿ� minput_filter () �ΰ��� + $ARG ��Ʊ���Ǥʤ��ƤϤʤ�ʤ��� */ + +MInputDriver minput_gui_driver; + +/*=*/ + +/***en + @brief Symbol of the name "xim". + + The variable Mxim is a symbol of name "xim". It is a name of the + input method driver #minput_xim_driver. */ +/***ja + @brief "xim"��̾���Ȥ��ƻ��ĥ���ܥ� . + + �ѿ� Mxim ��"xim"��̾���Ȥ��ƻ��ĥ���ܥ�Ǥ��롣"xim" + �����ϥ᥽�åɥɥ饤�� #minput_xim_driver ��̾���Ǥ��롣 */ + +MSymbol Mxim; + +/*=*/ + +/***en + @brief Convert an event to an input key. + + The minput_event_to_key () function returns the input key + corresponding to event $EVENT on $FRAME by a window system + dependent manner. + + In the m17n-X library, $EVENT must be a pointer to the structure + @c XKeyEvent, and it is handled as below. + + At first, the keysym name of $EVENT is acquired by the function @c + XKeysymToString. Then, the name is modified as below. + + If the name is one of "a" .. "z" and $EVENT has a Shift modifier, + the name is converted to "A" .. "Z" respectively, and the Shift + modifier is cleared. + + If the name is one byte length and $EVENT has a Control modifier, + the byte is bitwise anded by 0x1F and the Control modifier is + cleared. + + If $EVENT still has modifiers, the name is preceded by "S-" + (Shift), "C-" (Control), "M-" (Meta), "A-" (Alt), "G-" (AltGr), + "s-" (Super), and "H-" (Hyper) in this order. + + For instance, if the keysym name is "a" and the event has Shift, + Meta, and Hyper modifiers, the resulting name is "M-H-A". + + At last, a symbol who has the name is returned. */ + +/***ja + @brief ���٥�Ȥ����ϥ������Ѵ�����. + + �ؿ� minput_event_to_key () �ϡ�$FRAME �Υ��٥�� $EVENT + ���б��������ϥ������֤��������ǤΡ��б��פϥ�����ɥ������ƥ�˰�¸���롣 + + m17n-X �饤�֥��ξ��ˤϡ�$EVENT �� ��¤�� @c XKeyEvent + �ؤΥݥ��󥿤Ǥ��ꡢ���Τ褦�˽�������롣 + + �ޤ����ؿ� @c XKeysymToString �ˤ�äơ�$EVENT �� keysym + ̾��������������ǰʲ����ѹ���ä��롣 + + ̾���� "a" .. "z" �Τ����줫�Ǥ��ä� $EVENT �� Shift + ��ǥ��ե�����������С�̾���Ϥ��줾�� "A" .. "Z" ���Ѵ����졢Shift + ��ǥ��ե������ϼ�������롣 + + ̾�������Х���Ĺ�� $EVENT �� Control ��ǥ��ե�����������С�̾���� + 0x1F �Ȥ�ӥå�ñ�̤� and �黻����Control ��ǥ��ե������ϼ�������롣 + + ����Ǥ� $EVENT �ˤޤ���ǥ��ե�����������С�̾�������ˤ��줾�� + "S-" (Shift), "C-" (Control), "M-" (Meta), "A-" (Alt), , "G-" (AltGr), + "s-" (Super), "H-" (Hyper)�����ν��֤��դ��� + + ���Ȥ��С�keysym ̾�� "a" �ǥ��٥�Ȥ� Shift, Meta, and Hyper + ��ǥ��ե���������ƤС�������̾���� "M-H-A" �Ǥ��롣 + + �Ǹ�ˤ���̾������ĥ���ܥ���֤���*/ + + +MSymbol +minput_event_to_key (MFrame *frame, void *event) +{ + int modifiers; + MSymbol key; + char *name, *str; + + M_CHECK_READABLE (frame, MERROR_IM, Mnil); + key = (*frame->driver->parse_event) (frame, event, &modifiers); + if (! modifiers) + return key; + + name = msymbol_name (key); + str = alloca (strlen (name) + 2 * 8 + 1); + str[0] = '\0'; + if (modifiers & MINPUT_KEY_SHIFT_MODIFIER) + strcat (str, "S-"); + if (modifiers & MINPUT_KEY_CONTROL_MODIFIER) + strcat (str, "C-"); + if (modifiers & MINPUT_KEY_META_MODIFIER) + strcat (str, "M-"); + if (modifiers & MINPUT_KEY_ALT_MODIFIER) + strcat (str, "A-"); + if (modifiers & MINPUT_KEY_ALTGR_MODIFIER) + strcat (str, "G-"); + if (modifiers & MINPUT_KEY_SUPER_MODIFIER) + strcat (str, "s-"); + if (modifiers & MINPUT_KEY_HYPER_MODIFIER) + strcat (str, "H-"); + strcat (str, name); + + return msymbol (str); +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/input.c b/src/input.c new file mode 100644 index 0000000..d72e222 --- /dev/null +++ b/src/input.c @@ -0,0 +1,7014 @@ +/* input.c -- input method module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nInputMethod + @brief API for Input method. + + An input method is an object to enable inputting various + characters. An input method is identified by a pair of symbols, + LANGUAGE and NAME. This pair decides an input method driver of the + input method. An input method driver is a set of functions for + handling the input method. There are two kinds of input methods; + internal one and foreign one. + +
    +
  • Internal Input Method + + An internal input method has non @c Mnil LANGUAGE, and its body is + defined in the m17n database by the tag . For this kind of input methods, the m17n library uses two + predefined input method drivers, one for CUI use and the other for + GUI use. Those drivers utilize the input processing engine + provided by the m17n library itself. The m17n database may + provide input methods that are not limited to a specific language. + The database uses @c Mt as LANGUAGE of those input methods. + + An internal input method accepts an input key which is a symbol + associated with an input event. As there is no way for the @c + m17n @c library to know how input events are represented in an + application program, an application programmer has to convert an + input event to an input key by himself. See the documentation of + the function minput_event_to_key () for the detail. + +
  • Foreign Input Method @anchor foreign-input-method + + A foreign input method has @c Mnil LANGUAGE, and its body is + defined in an external resource (e.g. XIM of X Window System). + For this kind of input methods, the symbol NAME must have a + property of key #Minput_driver, and the value must be a pointer + to an input method driver. Therefore, by preparing a proper + driver, any kind of input method can be treated in the framework + of the @c m17n @c library. + + For convenience, the m17n-X library provides an input method + driver that enables the input style of OverTheSpot for XIM, and + stores #Minput_driver property of the symbol @c Mxim with a + pointer to the driver. See the documentation of m17n GUI API for + the detail. + +
+ + PROCESSING FLOW + + The typical processing flow of handling an input method is: + + @li open an input method + @li create an input context for the input method + @li filter an input key + @li look up a produced text in the input context */ + +/*=*/ +/***ja + @addtogroup m17nInputMethod + @brief ���ϥ᥽�å���API. + + ���ϥ᥽�åɤ�¿�ͤ�ʸ�������Ϥ��뤿��Υ��֥������ȤǤ��롣 + ���ϥ᥽�åɤϥ���ܥ� LANGUAGE �� NAME ���Ȥˤ�äƼ��̤��졢 + �����ȹ礻�ˤ�ä����ϥ᥽�åɥɥ饤�Ф����ꤹ�롣 + ���ϥ᥽�åɥɥ饤�ФȤϡ��������ϥ᥽�åɤ򰷤�����δؿ��ν��ޤ�Ǥ��롣 + ���ϥ᥽�åɤˤ������᥽�åɤȳ����᥽�åɤ�����ब���롣 + +
    +
  • �������ϥ᥽�å� + + �������ϥ᥽�åɤȤ� LANGUAGE �� @c Mnil �ʳ��Τ�ΤǤ��ꡢ�������� + ��m17n �ǡ����١����� �Ȥ����������� + �����������Ƥ��롣���μ�����ϥ᥽�åɤ��Ф��ơ�m17n �饤�֥��� + ��CUI �Ѥ� GUI �Ѥ��줾������ϥ᥽�åɥɥ饤�Ф򤢤餫����������� + ���롣�����Υɥ饤�Ф� m17n �饤�֥�꼫�Τ����Ͻ������󥸥���� + �Ѥ��롣m17n �ǡ����١����ˤϡ�����θ������ѤǤʤ����ϥ᥽�åɤ��� + �����뤳�Ȥ�Ǥ������Τ褦�����ϥ᥽�åɤ� LANGUAGE �� @c Mt �Ǥ��롣 + + �������ϥ᥽�åɤϡ��桼�������ϥ��٥�Ȥ��б���������ܥ�Ǥ����� + �ϥ����������롣@c m17n @c �饤�֥�� �����ϥ��٥�Ȥ����ץꥱ�� + �����ץ������Ǥɤ�ɽ������Ƥ��뤫���Τ뤳�Ȥ��Ǥ��ʤ��Τǡ��� + �ϥ��٥�Ȥ������ϥ����ؤ��Ѵ��ϥ��ץꥱ�������ץ�����ޤ���Ǥ�� + �Ԥ�ʤ��ƤϤʤ�ʤ����ܺ٤ˤĤ��Ƥϴؿ� minput_event_to_key () �� + �����򻲾ȡ� + +
  • �������ϥ᥽�å� @anchor foreign-input-method + + �������ϥ᥽�åɤȤ� LANGUAGE �� @c Mnil �Τ�ΤǤ��ꡢ�������Τϳ� + ���Υ꥽�����Ȥ����������롣�ʤ��Ȥ���X Window System ��XIM �� + �ɡ�) ���μ�����ϥ᥽�åɤǤϡ�����ܥ� NAME �� #Minput_driver �� + �����Ȥ���ץ��ѥƥ�������������ͤ����ϥ᥽�åɥɥ饤�ФؤΥݥ��� + ���Ǥ��롣���Τ��Ȥˤ�ꡢŬ�ڤʥɥ饤�Ф�������뤳�Ȥˤ�äơ��� + ���ʤ��������ϥ᥽�åɤ�@c m17n @c �饤�֥�� �����Ȥ���ǰ����� + ���Ǥ��롣 + + �������δ������顢m17n X �饤�֥��� XIM �� OverTheSpot �����ϥ��� + �����¸��������ϥ᥽�åɥɥ饤�Ф��󶡤����ޤ�����ܥ� @c Mxim �� + #Minput_driver �ץ��ѥƥ����ͤȤ��Ƥ��Υɥ饤�ФؤΥݥ��󥿤��ݻ� + ���Ƥ��롣�ܺ٤ˤĤ��Ƥ� m17n GUI API �Υɥ�����Ȥ򻲾ȤΤ��ȡ� + +
+ + ������ή�� + + ���ϥ᥽�åɽ�����ŵ��Ū�ʽ����ϰʲ��Τ褦�ˤʤ롣 + + @li ���ϥ᥽�åɤΥ����ץ� + @li �������ϥ᥽�åɤ����ϥ���ƥ����Ȥ����� + @li ���ϥ��٥�ȤΥե��륿 + @li ���ϥ���ƥ����ȤǤ������ƥ����Ȥθ��� */ + +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#ifdef HAVE_DLFCN_H +#include +#endif + +#include "m17n.h" +#include "m17n-misc.h" +#include "internal.h" +#include "mtext.h" +#include "input.h" +#include "symbol.h" +#include "plist.h" +#include "database.h" +#include "charset.h" + +static int mdebug_flag = MDEBUG_INPUT; + +static int fully_initialized; + +/** Symbols to load an input method data. */ +static MSymbol Mtitle, Mmacro, Mmodule, Mstate, Minclude; + +/** Symbols for actions. */ +static MSymbol Minsert, Mdelete, Mmark, Mmove, Mpushback, Mundo, Mcall, Mshift; +static MSymbol Mselect, Mshow, Mhide, Mcommit, Munhandle, Mpop; +static MSymbol Mset, Madd, Msub, Mmul, Mdiv, Mequal, Mless, Mgreater; +static MSymbol Mless_equal, Mgreater_equal; +static MSymbol Mcond; +static MSymbol Mplus, Mminus, Mstar, Mslash, Mand, Mor, Mnot; +static MSymbol Mswitch_im, Mpush_im, Mpop_im; + +/** Special action symbol. */ +static MSymbol Mat_reload; + +static MSymbol M_candidates; + +static MSymbol Mcandidate_list, Mcandidate_index; + +static MSymbol Minit, Mfini; + +/** Symbols for variables. */ +static MSymbol Mcandidates_group_size, Mcandidates_charset; +static MSymbol Mfallback_input_method; + +/** Symbols for key events. */ +static MSymbol one_char_symbol[256]; + +static MSymbol M_key_alias; + +static MSymbol Mdescription, Mcommand, Mvariable, Mglobal, Mconfig; + +static MSymbol M_gettext; + +/** Structure to hold a map. */ + +struct MIMMap +{ + /** List of actions to take when we reach the map. In a root map, + the actions are executed only when there is no more key. */ + MPlist *map_actions; + + /** List of deeper maps. If NULL, this is a terminal map. */ + MPlist *submaps; + + /** List of actions to take when we leave the map successfully. In + a root map, the actions are executed only when none of submaps + handle the current key. */ + MPlist *branch_actions; +}; + +typedef MPlist *(*MIMExternalFunc) (MPlist *plist); + +typedef struct +{ + MSymbol name; + void *handle; + MPlist *func_list; /* function name vs (MIMExternalFunc *) */ +} MIMExternalModule; + +struct MIMState +{ + M17NObject control; + + /** Name of the state. */ + MSymbol name; + + /** Title of the state, or NULL. */ + MText *title; + + /** Key translation map of the state. Built by merging all maps of + branches. */ + MIMMap *map; +}; + +#define CUSTOM_FILE "config.mic" + +static MPlist *load_im_info_keys; + +/* List of input method information. The format is: + (LANGUAGE NAME t:IM_INFO ... ... ...) */ +static MPlist *im_info_list; + +/* Database for user's customization file. */ +static MDatabase *im_custom_mdb; + +/* List of input method information loaded from im_custom_mdb. The + format is the same as im_info_list. */ +static MPlist *im_custom_list; + +/* List of input method information configured by + minput_config_command and minput_config_variable. The format is + the same as im_info_list. */ +static MPlist *im_config_list; + +/* Global input method information. It points into the element of + im_info_list corresponding to LANGUAGE == `nil' and NAME == + `global'. */ +static MInputMethodInfo *global_info; + +/* List of fallback input methods: well-formed plist of this form: + ((im-lang1 im-name1) (im-lang2 im-name2) ...) + The elements are in reverse preference order. */ + +static MPlist *fallback_input_methods; + +static int update_global_info (void); +static int update_custom_info (void); +static MInputMethodInfo *get_im_info (MSymbol, MSymbol, MSymbol, MSymbol); + + +/* Initialize fallback_input_methods. Called by fully_initialize () + after fully_initialized is set to 1. */ + +static void +prepare_fallback_input_methods () +{ + MPlist *plist, *pl, *p; + + fallback_input_methods = mplist (); + if ((plist = minput_get_variable (Mt, Mnil, Mfallback_input_method)) == NULL) + return; + plist = MPLIST_PLIST (plist); + plist = MPLIST_NEXT (plist); /* skip name */ + plist = MPLIST_NEXT (plist); /* skip description */ + plist = MPLIST_NEXT (plist); /* skip status */ + if (! plist) + return; + /* Now PLIST must be "LANGUAGE-NAME, ..." */ + if (MPLIST_MTEXT_P (plist)) + { + plist = minput_parse_im_names (MPLIST_MTEXT (plist)); + MPLIST_DO (p, plist) + if (MPLIST_KEY (p) == Mplist) + mplist_push (fallback_input_methods, Mplist, MPLIST_VAL (p)); + M17N_OBJECT_UNREF (plist); + } +} + +static void +fully_initialize () +{ + char *key_names[32] + = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "BackSpace", "Tab", "Linefeed", "Clear", NULL, "Return", NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "Escape", NULL, NULL, NULL, NULL }; + char buf[6], buf2[32], buf3[2]; + int i, j; + /* Maximum case: '\215', C-M-m, C-M-M, M-Return, C-A-m, C-A-M, A-Return + plus one for cyclic alias. */ + MSymbol alias[8]; + + M_key_alias = msymbol (" key-alias"); + + buf3[1] = '\0'; + + /* Aliases for 0x00-0x1F */ + buf[0] = 'C'; + buf[1] = '-'; + buf[3] = '\0'; + for (i = 0, buf[2] = '@'; i < ' '; i++, buf[2]++) + { + j = 0; + buf3[0] = i; + alias[j++] = msymbol (buf3); + alias[j++] = one_char_symbol[i] = msymbol (buf); + if (key_names[i] || (buf[2] >= 'A' && buf[2] <= 'Z')) + { + if (key_names[i]) + { + /* Ex: `Escape' == `C-[' */ + alias[j++] = msymbol (key_names[i]); + } + if (buf[2] >= 'A' && buf[2] <= 'Z') + { + /* Ex: `C-a' == `C-A' */ + buf[2] += 32; + alias[j++] = msymbol (buf); + buf[2] -= 32; + } + } + /* Establish cyclic alias chain. */ + alias[j] = alias[0]; + while (--j >= 0) + msymbol_put (alias[j], M_key_alias, alias[j + 1]); + } + + /* Aliases for 0x20-0x7E */ + buf[0] = 'S'; + for (i = buf[2] = ' '; i < 127; i++, buf[2]++) + { + one_char_symbol[i] = msymbol (buf + 2); + if (i >= 'A' && i <= 'Z') + { + /* Ex: `A' == `S-A' == `S-a'. */ + alias[0] = alias[3] = one_char_symbol[i]; + alias[1] = msymbol (buf); + buf[2] += 32; + alias[2] = msymbol (buf); + buf[2] -= 32; + for (j = 0; j < 3; j++) + msymbol_put (alias[j], M_key_alias, alias[j + 1]); + } + } + + /* Aliases for 0x7F */ + buf3[0] = 0x7F; + alias[0] = alias[3] = msymbol (buf3); + alias[1] = one_char_symbol[127] = msymbol ("Delete"); + alias[2] = msymbol ("C-?"); + for (j = 0; j < 3; j++) + msymbol_put (alias[j], M_key_alias, alias[j + 1]); + + /* Aliases for 0x80-0x9F */ + buf[0] = 'C'; + /* buf[1] = '-'; -- already done */ + buf[3] = '-'; + buf[5] = '\0'; + buf2[1] = '-'; + for (i = 128, buf[4] = '@'; i < 160; i++, buf[4]++) + { + j = 0; + buf3[0] = i; + alias[j++] = msymbol (buf3); + /* `C-M-a' == `C-A-a' */ + buf[2] = 'M'; + alias[j++] = one_char_symbol[i] = msymbol (buf); + buf[2] = 'A'; + alias[j++] = msymbol (buf); + if (key_names[i - 128]) + { + /* Ex: `M-Escape' == `A-Escape' == `C-M-['. */ + buf2[0] = 'M'; + strcpy (buf2 + 2, key_names[i - 128]); + alias[j++] = msymbol (buf2); + buf2[0] = 'A'; + alias[j++] = msymbol (buf2); + } + if (buf[4] >= 'A' && buf[4] <= 'Z') + { + /* Ex: `C-M-a' == `C-M-A'. */ + buf[4] += 32; + buf[2] = 'M'; + alias[j++] = msymbol (buf); + buf[2] = 'A'; + alias[j++] = msymbol (buf); + buf[4] -= 32; + } + + /* Establish cyclic alias chain. */ + alias[j] = alias[0]; + while (--j >= 0) + msymbol_put (alias[j], M_key_alias, alias[j + 1]); + } + + /* Aliases for 0xA0-0xFF */ + for (i = 160, buf[4] = ' '; i < 255; i++, buf[4]++) + { + j = 0; + buf3[0] = i; + alias[j++] = msymbol (buf3); + buf[2] = 'M'; + alias[j++] = one_char_symbol[i] = msymbol (buf + 2); + buf[2] = 'A'; + alias[j++] = msymbol (buf + 2); + alias[j]= alias[0]; + while (--j >= 0) + msymbol_put (alias[j], M_key_alias, alias[j + 1]); + } + + buf3[0] = (char) 255; + alias[0] = alias[3] = msymbol (buf3); + alias[1] = one_char_symbol[255] = msymbol ("M-Delete"); + alias[2] = msymbol ("A-Delete"); + for (j = 0; j < 3; j++) + msymbol_put (alias[j], M_key_alias, alias[j + 1]); + + /* Aliases for keys that can't be mapped to one-char-symbol + (e.g. C-A-1) */ + /* buf is already set to "C-?-". */ + for (i = ' '; i <= '~'; i++) + { + if (i == '@') + { + i = '_'; + continue; + } + if (i == 'a') + { + i = 'z'; + continue; + } + buf[2] = 'M'; + buf[4] = i; + alias[0] = alias[2] = msymbol (buf); + buf[2] = 'A'; + alias[1] = msymbol (buf); + for (j = 0; j < 2; j++) + msymbol_put (alias[j], M_key_alias, alias[j + 1]); + } + + Minput_method = msymbol ("input-method"); + Mtitle = msymbol ("title"); + Mmacro = msymbol ("macro"); + Mmodule = msymbol ("module"); + Mmap = msymbol ("map"); + Mstate = msymbol ("state"); + Minclude = msymbol ("include"); + Minsert = msymbol ("insert"); + M_candidates = msymbol (" candidates"); + Mdelete = msymbol ("delete"); + Mmove = msymbol ("move"); + Mmark = msymbol ("mark"); + Mpushback = msymbol ("pushback"); + Mpop = msymbol ("pop"); + Mundo = msymbol ("undo"); + Mcall = msymbol ("call"); + Mshift = msymbol ("shift"); + Mselect = msymbol ("select"); + Mshow = msymbol ("show"); + Mhide = msymbol ("hide"); + Mcommit = msymbol ("commit"); + Munhandle = msymbol ("unhandle"); + Mset = msymbol ("set"); + Madd = msymbol ("add"); + Msub = msymbol ("sub"); + Mmul = msymbol ("mul"); + Mdiv = msymbol ("div"); + Mequal = msymbol ("="); + Mless = msymbol ("<"); + Mgreater = msymbol (">"); + Mless_equal = msymbol ("<="); + Mgreater_equal = msymbol (">="); + Mcond = msymbol ("cond"); + Mplus = msymbol ("+"); + Mminus = msymbol ("-"); + Mstar = msymbol ("*"); + Mslash = msymbol ("/"); + Mand = msymbol ("&"); + Mor = msymbol ("|"); + Mnot = msymbol ("!"); + Mswitch_im = msymbol ("switch-im"); + Mpush_im = msymbol ("push-im"); + Mpop_im = msymbol ("pop-im"); + + Mat_reload = msymbol ("-reload"); + + Mcandidates_group_size = msymbol ("candidates-group-size"); + Mcandidates_charset = msymbol ("candidates-charset"); + Mfallback_input_method = msymbol ("fallback-input-method"); + + Mcandidate_list = msymbol_as_managing_key (" candidate-list"); + Mcandidate_index = msymbol (" candidate-index"); + + Minit = msymbol ("init"); + Mfini = msymbol ("fini"); + + Mdescription = msymbol ("description"); + Mcommand = msymbol ("command"); + Mvariable = msymbol ("variable"); + Mglobal = msymbol ("global"); + Mconfig = msymbol ("config"); + M_gettext = msymbol ("_"); + + load_im_info_keys = mplist (); + mplist_add (load_im_info_keys, Mstate, Mnil); + mplist_push (load_im_info_keys, Mmap, Mnil); + + im_info_list = mplist (); + im_config_list = im_custom_list = NULL; + im_custom_mdb = NULL; + update_custom_info (); + global_info = NULL; + update_global_info (); + + fully_initialized = 1; + prepare_fallback_input_methods (); +} + +#define MINPUT__INIT() \ + do { \ + if (! fully_initialized) \ + fully_initialize (); \ + } while (0) + + +static int +marker_code (MSymbol sym, int surrounding) +{ + char *name; + + if (sym == Mnil) + return -1; + name = MSYMBOL_NAME (sym); + return (name[0] != '@' ? -1 + : (((name[1] >= '0' && name[1] <= '9') + || name[1] == '<' || name[1] == '>' || name[1] == '=' + || name[1] == '[' || name[1] == ']' + || name[1] == '@') + && name[2] == '\0') ? name[1] + : (name[1] != '+' && name[1] != '-') ? -1 + : (name[2] == '\0' || surrounding) ? name[1] + : -1); +} + + +/* Return a plist containing an integer value of VAR. The plist must + not be UNREFed. */ + +static MPlist * +resolve_variable (MInputContextInfo *ic_info, MSymbol var) +{ + MPlist *plist = mplist__assq (ic_info->vars, var); + + if (plist) + { + plist = MPLIST_PLIST (plist); + return MPLIST_NEXT (plist); + } + + plist = mplist (); + mplist_push (ic_info->vars, Mplist, plist); + M17N_OBJECT_UNREF (plist); + plist = mplist_add (plist, Msymbol, var); + plist = mplist_add (plist, Minteger, (void *) 0); + return plist; +} + +static MText * +get_surrounding_text (MInputContext *ic, int len) +{ + MText *mt = NULL; + + mplist_push (ic->plist, Minteger, (void *) len); + if (minput_callback (ic, Minput_get_surrounding_text) >= 0 + && MPLIST_MTEXT_P (ic->plist)) + mt = MPLIST_MTEXT (ic->plist); + mplist_pop (ic->plist); + return mt; +} + +static void +delete_surrounding_text (MInputContext *ic, int pos) +{ + MInputContextInfo *ic_info = (MInputContextInfo *) ic->info; + + mplist_push (ic->plist, Minteger, (void *) pos); + minput_callback (ic, Minput_delete_surrounding_text); + mplist_pop (ic->plist); + if (pos < 0) + { + M17N_OBJECT_UNREF (ic_info->preceding_text); + ic_info->preceding_text = NULL; + } + else if (pos > 0) + { + M17N_OBJECT_UNREF (ic_info->following_text); + ic_info->following_text = NULL; + } +} + +static int +get_preceding_char (MInputContext *ic, int pos) +{ + MInputContextInfo *ic_info = (MInputContextInfo *) ic->info; + MText *mt; + int len; + + if (pos && ic_info->preceding_text) + { + len = mtext_nchars (ic_info->preceding_text); + if (pos <= len) + return mtext_ref_char (ic_info->preceding_text, len - pos); + } + mt = get_surrounding_text (ic, - pos); + if (! mt) + return -2; + len = mtext_nchars (mt); + if (ic_info->preceding_text) + { + if (mtext_nchars (ic_info->preceding_text) < len) + { + M17N_OBJECT_UNREF (ic_info->preceding_text); + ic_info->preceding_text = mt; + } + else + M17N_OBJECT_UNREF (mt); + } + else + ic_info->preceding_text = mt; + if (pos > len) + return -1; + return mtext_ref_char (ic_info->preceding_text, len - pos); +} + +static int +get_following_char (MInputContext *ic, int pos) +{ + MInputContextInfo *ic_info = (MInputContextInfo *) ic->info; + MText *mt; + int len; + + if (ic_info->following_text) + { + len = mtext_nchars (ic_info->following_text); + if (pos < len) + return mtext_ref_char (ic_info->following_text, pos); + } + mt = get_surrounding_text (ic, pos + 1); + if (! mt) + return -2; + len = mtext_nchars (mt); + if (ic_info->following_text) + { + if (mtext_nchars (ic_info->following_text) < len) + { + M17N_OBJECT_UNREF (ic_info->following_text); + ic_info->following_text = mt; + } + else + M17N_OBJECT_UNREF (mt); + } + else + ic_info->following_text = mt; + if (pos >= len) + return -1; + return mtext_ref_char (ic_info->following_text, pos); +} + +static int +surrounding_pos (MSymbol sym, int *pos) +{ + char *name; + + if (sym == Mnil) + return 0; + name = MSYMBOL_NAME (sym); + if (name[0] == '@' + && (name[1] == '-' ? (name[2] >= '1' && name[2] <= '9') + : name[1] == '+' ? (name[2] >= '0' && name[2] <= '9') + : 0)) + { + *pos = name[1] == '-' ? - atoi (name + 2) : atoi (name + 2); + return 1; + } + return 0; +} + +static int +integer_value (MInputContext *ic, MPlist *arg, int surrounding) +{ + MInputContextInfo *ic_info = (MInputContextInfo *) ic->info; + int code, pos; + MText *preedit = ic->preedit; + int len = mtext_nchars (preedit); + + if (MPLIST_INTEGER_P (arg)) + return MPLIST_INTEGER (arg); + + code = marker_code (MPLIST_SYMBOL (arg), surrounding); + if (code < 0) + { + MPlist *val = resolve_variable (ic_info, MPLIST_SYMBOL (arg)); + + return (MPLIST_INTEGER_P (val) ? MPLIST_INTEGER (val) : 0); + } + if (code == '@') + return ic_info->key_head; + if ((code == '-' || code == '+')) + { + char *name = MSYMBOL_NAME (MPLIST_SYMBOL (arg)); + + if (name[2]) + { + pos = atoi (name + 1); + if (pos == 0 && code == '-') + return get_preceding_char (ic, 0); + pos = ic->cursor_pos + pos; + if (pos < 0) + { + if (ic->produced && mtext_len (ic->produced) + pos >= 0) + return mtext_ref_char (ic->produced, + mtext_len (ic->produced) + pos); + return get_preceding_char (ic, - pos); + } + else if (pos >= len) + return get_following_char (ic, pos - len); + } + else + pos = ic->cursor_pos + (code == '+' ? 1 : -1); + } + else if (code >= '0' && code <= '9') + pos = code - '0'; + else if (code == '=') + pos = ic->cursor_pos; + else if (code == '[') + pos = ic->cursor_pos - 1; + else if (code == ']') + pos = ic->cursor_pos + 1; + else if (code == '<') + pos = 0; + else if (code == '>') + pos = len - 1; + return (pos >= 0 && pos < len ? mtext_ref_char (preedit, pos) : -1); +} + +static int +parse_expression (MPlist *plist) +{ + MSymbol op; + + if (MPLIST_INTEGER_P (plist) || MPLIST_SYMBOL_P (plist)) + return 0; + if (! MPLIST_PLIST_P (plist)) + return -1; + plist = MPLIST_PLIST (plist); + op = MPLIST_SYMBOL (plist); + if (op != Mplus && op != Mminus && op != Mstar && op != Mslash + && op != Mand && op != Mor && op != Mnot + && op != Mless && op != Mgreater && op != Mequal + && op != Mless_equal && op != Mgreater_equal) + MERROR (MERROR_IM, -1); + MPLIST_DO (plist, MPLIST_NEXT (plist)) + if (parse_expression (plist) < 0) + return -1; + return 0; +} + +static int +resolve_expression (MInputContext *ic, MPlist *plist) +{ + int val; + MSymbol op; + + if (MPLIST_INTEGER_P (plist)) + return MPLIST_INTEGER (plist); + if (MPLIST_SYMBOL_P (plist)) + return integer_value (ic, plist, 1); + if (! MPLIST_PLIST_P (plist)) + return 0; + plist = MPLIST_PLIST (plist); + if (! MPLIST_SYMBOL_P (plist)) + return 0; + op = MPLIST_SYMBOL (plist); + plist = MPLIST_NEXT (plist); + val = resolve_expression (ic, plist); + if (op == Mplus) + MPLIST_DO (plist, MPLIST_NEXT (plist)) + val += resolve_expression (ic, plist); + else if (op == Mminus) + MPLIST_DO (plist, MPLIST_NEXT (plist)) + val -= resolve_expression (ic, plist); + else if (op == Mstar) + MPLIST_DO (plist, MPLIST_NEXT (plist)) + val *= resolve_expression (ic, plist); + else if (op == Mslash) + MPLIST_DO (plist, MPLIST_NEXT (plist)) + val /= resolve_expression (ic, plist); + else if (op == Mand) + MPLIST_DO (plist, MPLIST_NEXT (plist)) + val &= resolve_expression (ic, plist); + else if (op == Mor) + MPLIST_DO (plist, MPLIST_NEXT (plist)) + val |= resolve_expression (ic, plist); + else if (op == Mnot) + val = ! val; + else if (op == Mless) + val = val < resolve_expression (ic, MPLIST_NEXT (plist)); + else if (op == Mequal) + val = val == resolve_expression (ic, MPLIST_NEXT (plist)); + else if (op == Mgreater) + val = val > resolve_expression (ic, MPLIST_NEXT (plist)); + else if (op == Mless_equal) + val = val <= resolve_expression (ic, MPLIST_NEXT (plist)); + else if (op == Mgreater_equal) + val = val >= resolve_expression (ic, MPLIST_NEXT (plist)); + return val; +} + +/* Parse PLIST as an action list. PLIST should have this form: + PLIST ::= ( (ACTION-NAME ACTION-ARG *) *). + Return 0 if successfully parsed, otherwise return -1. */ + +static int +parse_action_list (MPlist *plist, MPlist *macros) +{ + MPLIST_DO (plist, plist) + { + if (MPLIST_MTEXT_P (plist)) + { + /* This is a short form of (insert MTEXT). */ + /* if (mtext_nchars (MPLIST_MTEXT (plist)) == 0) + MERROR (MERROR_IM, -1); */ + } + else if (MPLIST_PLIST_P (plist) + && (MPLIST_MTEXT_P (MPLIST_PLIST (plist)) + || MPLIST_PLIST_P (MPLIST_PLIST (plist)))) + { + MPlist *pl; + + /* This is a short form of (insert (GROUPS *)). */ + MPLIST_DO (pl, MPLIST_PLIST (plist)) + { + if (MPLIST_PLIST_P (pl)) + { + MPlist *elt; + + MPLIST_DO (elt, MPLIST_PLIST (pl)) + if (! MPLIST_MTEXT_P (elt) + || mtext_nchars (MPLIST_MTEXT (elt)) == 0) + MERROR (MERROR_IM, -1); + } + else + { + if (! MPLIST_MTEXT_P (pl) + || mtext_nchars (MPLIST_MTEXT (pl)) == 0) + MERROR (MERROR_IM, -1); + } + } + } + else if (MPLIST_INTEGER_P (plist)) + { + int c = MPLIST_INTEGER (plist); + + if (c < 0 || c > MCHAR_MAX) + MERROR (MERROR_IM, -1); + } + else if (MPLIST_PLIST_P (plist) + && MPLIST_SYMBOL_P (MPLIST_PLIST (plist))) + { + MPlist *pl = MPLIST_PLIST (plist); + MSymbol action_name = MPLIST_SYMBOL (pl); + + pl = MPLIST_NEXT (pl); + + if (action_name == M_candidates) + { + /* This is an already regularised action. */ + continue; + } + if (action_name == Minsert) + { + if (MPLIST_MTEXT_P (pl)) + { + if (mtext_nchars (MPLIST_MTEXT (pl)) == 0) + MERROR (MERROR_IM, -1); + } + else if (MPLIST_INTEGER_P (pl)) + { + int c = MPLIST_INTEGER (pl); + + if (c < 0 || c > MCHAR_MAX) + MERROR (MERROR_IM, -1); + } + else if (MPLIST_PLIST_P (pl)) + { + MPLIST_DO (pl, MPLIST_PLIST (pl)) + { + if (MPLIST_PLIST_P (pl)) + { + MPlist *elt; + + MPLIST_DO (elt, MPLIST_PLIST (pl)) + if (! MPLIST_MTEXT_P (elt) + || mtext_nchars (MPLIST_MTEXT (elt)) == 0) + MERROR (MERROR_IM, -1); + } + else + { + if (! MPLIST_MTEXT_P (pl) + || mtext_nchars (MPLIST_MTEXT (pl)) == 0) + MERROR (MERROR_IM, -1); + } + } + } + else if (! MPLIST_SYMBOL_P (pl)) + MERROR (MERROR_IM, -1); + } + else if (action_name == Mselect + || action_name == Mdelete + || action_name == Mmove) + { + if (parse_expression (pl) < 0) + return -1; + } + else if (action_name == Mmark + || action_name == Mcall + || action_name == Mshift) + { + if (! MPLIST_SYMBOL_P (pl)) + MERROR (MERROR_IM, -1); + } + else if (action_name == Mundo) + { + if (! MPLIST_TAIL_P (pl)) + { + if (! MPLIST_SYMBOL_P (pl) + && ! MPLIST_INTEGER_P (pl)) + MERROR (MERROR_IM, -1); + } + } + else if (action_name == Mpushback) + { + if (MPLIST_MTEXT_P (pl)) + { + MText *mt = MPLIST_MTEXT (pl); + + if (mtext_nchars (mt) != mtext_nbytes (mt)) + MERROR (MERROR_IM, -1); + } + else if (MPLIST_PLIST_P (pl)) + { + MPlist *p; + + MPLIST_DO (p, MPLIST_PLIST (pl)) + if (! MPLIST_SYMBOL_P (p)) + MERROR (MERROR_IM, -1); + } + else if (! MPLIST_INTEGER_P (pl)) + MERROR (MERROR_IM, -1); + } + else if (action_name == Mset || action_name == Madd + || action_name == Msub || action_name == Mmul + || action_name == Mdiv) + { + if (! MPLIST_SYMBOL_P (pl)) + MERROR (MERROR_IM, -1); + if (parse_expression (MPLIST_NEXT (pl)) < 0) + return -1; + } + else if (action_name == Mequal || action_name == Mless + || action_name == Mgreater || action_name == Mless_equal + || action_name == Mgreater_equal) + { + if (parse_expression (pl) < 0 + || parse_expression (MPLIST_NEXT (pl)) < 0) + return -1; + pl = MPLIST_NEXT (MPLIST_NEXT (pl)); + if (! MPLIST_PLIST_P (pl)) + MERROR (MERROR_IM, -1); + if (parse_action_list (MPLIST_PLIST (pl), macros) < 0) + MERROR (MERROR_IM, -1); + pl = MPLIST_NEXT (pl); + if (MPLIST_PLIST_P (pl) + && parse_action_list (MPLIST_PLIST (pl), macros) < 0) + MERROR (MERROR_IM, -1); + } + else if (action_name == Mshow || action_name == Mhide + || action_name == Mcommit || action_name == Munhandle + || action_name == Mpop + || action_name == Mpush_im || action_name == Mpop_im + || action_name == Mswitch_im) + ; + else if (action_name == Mcond) + { + MPLIST_DO (pl, pl) + if (! MPLIST_PLIST_P (pl)) + MERROR (MERROR_IM, -1); + } + else if (! macros || ! mplist_get (macros, action_name)) + MERROR (MERROR_IM, -1); + } + else if (! MPLIST_SYMBOL_P (plist)) + MERROR (MERROR_IM, -1); + } + + return 0; +} + +static MPlist * +resolve_command (MPlist *cmds, MSymbol command) +{ + MPlist *plist; + + if (! cmds || ! (plist = mplist__assq (cmds, command))) + return NULL; + plist = MPLIST_PLIST (plist); /* (NAME DESC STATUS [KEYSEQ ...]) */ + plist = MPLIST_NEXT (plist); + plist = MPLIST_NEXT (plist); + plist = MPLIST_NEXT (plist); + return plist; +} + +/* Load a translation into MAP from PLIST. + PLIST has this form: + PLIST ::= ( KEYSEQ MAP-ACTION * ) */ + +static int +load_translation (MIMMap *map, MPlist *keylist, MPlist *map_actions, + MPlist *branch_actions, MPlist *macros) +{ + MSymbol *keyseq; + int len, i; + + if (MPLIST_MTEXT_P (keylist)) + { + MText *mt = MPLIST_MTEXT (keylist); + + len = mtext_nchars (mt); + if (MFAILP (len > 0 && len == mtext_nbytes (mt))) + return -1; + keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len); + for (i = 0; i < len; i++) + keyseq[i] = one_char_symbol[MTEXT_DATA (mt)[i]]; + } + else + { + MPlist *elt; + + if (MFAILP (MPLIST_PLIST_P (keylist))) + return -1; + elt = MPLIST_PLIST (keylist); + len = MPLIST_LENGTH (elt); + if (MFAILP (len > 0)) + return -1; + keyseq = (MSymbol *) alloca (sizeof (MSymbol) * len); + for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt)) + { + if (MPLIST_INTEGER_P (elt)) + { + int c = MPLIST_INTEGER (elt); + + if (MFAILP (c >= 0 && c < 0x100)) + return -1; + keyseq[i] = one_char_symbol[c]; + } + else + { + if (MFAILP (MPLIST_SYMBOL_P (elt))) + return -1; + keyseq[i] = MPLIST_SYMBOL (elt); + } + } + } + + for (i = 0; i < len; i++) + { + MIMMap *deeper = NULL; + + if (map->submaps) + deeper = mplist_get (map->submaps, keyseq[i]); + else + map->submaps = mplist (); + if (! deeper) + { + /* Fixme: It is better to make all deeper maps at once. */ + MSTRUCT_CALLOC (deeper, MERROR_IM); + mplist_put (map->submaps, keyseq[i], deeper); + } + map = deeper; + } + + /* We reach a terminal map. */ + if (map->map_actions + || map->branch_actions) + /* This map is already defined. We avoid overriding it. */ + return 0; + + if (! MPLIST_TAIL_P (map_actions)) + { + if (parse_action_list (map_actions, macros) < 0) + MERROR (MERROR_IM, -1); + map->map_actions = map_actions; + } + if (branch_actions) + { + map->branch_actions = branch_actions; + M17N_OBJECT_REF (branch_actions); + } + + return 0; +} + +/* Load a branch from PLIST into MAP. PLIST has this form: + PLIST ::= ( MAP-NAME BRANCH-ACTION * ) */ + +static int +load_branch (MInputMethodInfo *im_info, MPlist *plist, MIMMap *map) +{ + MSymbol map_name; + MPlist *branch_actions; + + if (MFAILP (MPLIST_SYMBOL_P (plist))) + return -1; + map_name = MPLIST_SYMBOL (plist); + plist = MPLIST_NEXT (plist); + if (MPLIST_TAIL_P (plist)) + branch_actions = NULL; + else if (MFAILP (parse_action_list (plist, im_info->macros) >= 0)) + return -1; + else + branch_actions = plist; + if (map_name == Mnil) + { + map->branch_actions = branch_actions; + if (branch_actions) + M17N_OBJECT_REF (branch_actions); + } + else if (map_name == Mt) + { + map->map_actions = branch_actions; + if (branch_actions) + M17N_OBJECT_REF (branch_actions); + } + else if (im_info->maps) + { + plist = (MPlist *) mplist_get (im_info->maps, map_name); + if (! plist && im_info->configured_vars) + { + MPlist *p = mplist__assq (im_info->configured_vars, map_name); + + if (p && MPLIST_PLIST_P (p)) + { + p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p)))); + if (MPLIST_SYMBOL_P (p)) + plist = mplist_get (im_info->maps, MPLIST_SYMBOL (p)); + } + } + if (plist) + { + MPLIST_DO (plist, plist) + { + MPlist *keylist, *map_actions; + + if (! MPLIST_PLIST_P (plist)) + MERROR (MERROR_IM, -1); + keylist = MPLIST_PLIST (plist); + map_actions = MPLIST_NEXT (keylist); + if (MPLIST_SYMBOL_P (keylist)) + { + MSymbol command = MPLIST_SYMBOL (keylist); + MPlist *pl; + + if (MFAILP (command != Mat_reload)) + continue; + pl = resolve_command (im_info->configured_cmds, command); + if (MFAILP (pl)) + continue; + MPLIST_DO (pl, pl) + load_translation (map, pl, map_actions, branch_actions, + im_info->macros); + } + else + load_translation (map, keylist, map_actions, branch_actions, + im_info->macros); + } + } + } + + return 0; +} + +/* Load a macro from PLIST into IM_INFO->macros. + PLIST has this form: + PLIST ::= ( MACRO-NAME ACTION * ) + IM_INFO->macros is a plist of macro names vs action list. */ + +static int +load_macros (MInputMethodInfo *im_info, MPlist *plist) +{ + MSymbol name; + MPlist *pl; + + if (! MPLIST_SYMBOL_P (plist)) + MERROR (MERROR_IM, -1); + name = MPLIST_SYMBOL (plist); + plist = MPLIST_NEXT (plist); + if (MFAILP (! MPLIST_TAIL_P (plist))) + MERROR (MERROR_IM, -1); + pl = mplist_get (im_info->macros, name); + M17N_OBJECT_UNREF (pl); + mplist_put (im_info->macros, name, plist); + M17N_OBJECT_REF (plist); + return 0; +} + +/* Load an external module from PLIST, and return a pointer to + MIMExternalModule. + + PLIST has this form: + PLIST ::= ( MODULE-NAME FUNCTION * ) + IM_INFO->externals is a plist of MODULE-NAME vs (MIMExternalModule *). + + On error, return NULL. */ + +static MIMExternalModule * +load_external_module (MPlist *plist) +{ + void *handle; + MSymbol module; + char *module_file; + MIMExternalModule *external; + MPlist *func_list; + void *func; + + if (MPLIST_MTEXT_P (plist)) + module = msymbol ((char *) MTEXT_DATA (MPLIST_MTEXT (plist))); + else if (MPLIST_SYMBOL_P (plist)) + module = MPLIST_SYMBOL (plist); + module_file = alloca (strlen (M17N_MODULE_DIR) + 1 + + strlen (MSYMBOL_NAME (module)) + + strlen (DLOPEN_SHLIB_EXT) + 1); + sprintf (module_file, "%s/%s%s", + M17N_MODULE_DIR, MSYMBOL_NAME (module), DLOPEN_SHLIB_EXT); + + handle = dlopen (module_file, RTLD_NOW); + if (MFAILP (handle)) + return NULL; + func_list = mplist (); + MPLIST_DO (plist, MPLIST_NEXT (plist)) + { + if (! MPLIST_SYMBOL_P (plist)) + MERROR_GOTO (MERROR_IM, err_label); + func = dlsym (handle, MSYMBOL_NAME (MPLIST_SYMBOL (plist))); + if (MFAILP (func)) + goto err_label; + mplist_add (func_list, MPLIST_SYMBOL (plist), func); + } + + MSTRUCT_MALLOC (external, MERROR_IM); + external->name = module; + external->handle = handle; + external->func_list = func_list; + return external; + + err_label: + M17N_OBJECT_UNREF (func_list); + dlclose (handle); + return NULL; +} + +static void +unload_external_module (MIMExternalModule *external) +{ + dlclose (external->handle); + M17N_OBJECT_UNREF (external->func_list); + free (external); +} + +static void +free_map (MIMMap *map, int top) +{ + MPlist *plist; + + if (top) + M17N_OBJECT_UNREF (map->map_actions); + if (map->submaps) + { + MPLIST_DO (plist, map->submaps) + free_map ((MIMMap *) MPLIST_VAL (plist), 0); + M17N_OBJECT_UNREF (map->submaps); + } + M17N_OBJECT_UNREF (map->branch_actions); + free (map); +} + +static void +free_state (void *object) +{ + MIMState *state = object; + + M17N_OBJECT_UNREF (state->title); + if (state->map) + free_map (state->map, 1); + free (state); +} + +/** Load a state from PLIST into a newly allocated state object. + PLIST has this form: + PLIST ::= ( STATE-NAME STATE-TITLE ? BRANCH * ) + BRANCH ::= ( MAP-NAME BRANCH-ACTION * ) + Return the state object. */ + +static MIMState * +load_state (MInputMethodInfo *im_info, MPlist *plist) +{ + MIMState *state; + + if (MFAILP (MPLIST_SYMBOL_P (plist))) + return NULL; + M17N_OBJECT (state, free_state, MERROR_IM); + state->name = MPLIST_SYMBOL (plist); + plist = MPLIST_NEXT (plist); + if (MPLIST_MTEXT_P (plist)) + { + state->title = MPLIST_MTEXT (plist); + mtext_put_prop (state->title, 0, mtext_nchars (state->title), + Mlanguage, im_info->language); + M17N_OBJECT_REF (state->title); + plist = MPLIST_NEXT (plist); + } + MSTRUCT_CALLOC (state->map, MERROR_IM); + MPLIST_DO (plist, plist) + { + if (MFAILP (MPLIST_PLIST_P (plist))) + continue; + load_branch (im_info, MPLIST_PLIST (plist), state->map); + } + return state; +} + +/* Return a newly created IM_INFO for an input method specified by + LANUAGE, NAME, and EXTRA. IM_INFO is stored in PLIST. */ + +static MInputMethodInfo * +new_im_info (MDatabase *mdb, MSymbol language, MSymbol name, MSymbol extra, + MPlist *plist) +{ + MInputMethodInfo *im_info; + MPlist *elt; + + if (name == Mnil && extra == Mnil) + language = Mt, extra = Mglobal; + + MDEBUG_PRINT3 ("loading %s-%s %s\n", + msymbol_name (language), msymbol_name (name), (mdb ? "from mdb" : "")); + + MSTRUCT_CALLOC (im_info, MERROR_IM); + im_info->mdb = mdb; + im_info->language = language; + im_info->name = name; + im_info->extra = extra; + + elt = mplist (); + mplist_add (plist, Mplist, elt); + M17N_OBJECT_UNREF (elt); + elt = mplist_add (elt, Msymbol, language); + elt = mplist_add (elt, Msymbol, name); + elt = mplist_add (elt, Msymbol, extra); + mplist_add (elt, Mt, im_info); + + return im_info; +} + +static void +fini_im_info (MInputMethodInfo *im_info) +{ + MPlist *plist; + + M17N_OBJECT_UNREF (im_info->cmds); + M17N_OBJECT_UNREF (im_info->configured_cmds); + M17N_OBJECT_UNREF (im_info->bc_cmds); + M17N_OBJECT_UNREF (im_info->vars); + M17N_OBJECT_UNREF (im_info->configured_vars); + M17N_OBJECT_UNREF (im_info->bc_vars); + M17N_OBJECT_UNREF (im_info->description); + M17N_OBJECT_UNREF (im_info->title); + if (im_info->states) + { + MPLIST_DO (plist, im_info->states) + { + MIMState *state = (MIMState *) MPLIST_VAL (plist); + + M17N_OBJECT_UNREF (state); + } + M17N_OBJECT_UNREF (im_info->states); + } + + if (im_info->macros) + { + MPLIST_DO (plist, im_info->macros) + M17N_OBJECT_UNREF (MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (im_info->macros); + } + + if (im_info->externals) + { + MPLIST_DO (plist, im_info->externals) + { + unload_external_module (MPLIST_VAL (plist)); + MPLIST_KEY (plist) = Mt; + } + M17N_OBJECT_UNREF (im_info->externals); + } + if (im_info->maps) + { + MPLIST_DO (plist, im_info->maps) + { + MPlist *p = MPLIST_PLIST (plist); + + M17N_OBJECT_UNREF (p); + } + M17N_OBJECT_UNREF (im_info->maps); + } + + im_info->tick = 0; +} + +static void +free_im_info (MInputMethodInfo *im_info) +{ + MDEBUG_PRINT2 ("freeing %s-%s\n", msymbol_name (im_info->language), + msymbol_name (im_info->name)); + fini_im_info (im_info); + free (im_info); +} + +static void +free_im_list (MPlist *plist) +{ + MPlist *pl, *elt; + + MPLIST_DO (pl, plist) + { + MInputMethodInfo *im_info; + + elt = MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (pl)))); + im_info = MPLIST_VAL (elt); + free_im_info (im_info); + } + M17N_OBJECT_UNREF (plist); +} + +static MInputMethodInfo * +lookup_im_info (MPlist *plist, MSymbol language, MSymbol name, MSymbol extra) +{ + if (name == Mnil && extra == Mnil) + language = Mt, extra = Mglobal; + while ((plist = mplist__assq (plist, language))) + { + MPlist *elt = MPLIST_PLIST (plist); + + plist = MPLIST_NEXT (plist); + elt = MPLIST_NEXT (elt); + if (MPLIST_SYMBOL (elt) != name) + continue; + elt = MPLIST_NEXT (elt); + if (MPLIST_SYMBOL (elt) != extra) + continue; + elt = MPLIST_NEXT (elt); + return MPLIST_VAL (elt); + } + return NULL; +} + +static void load_im_info (MPlist *, MInputMethodInfo *); + +#define get_custom_info(im_info) \ + (im_custom_list \ + ? lookup_im_info (im_custom_list, (im_info)->language, \ + (im_info)->name, (im_info)->extra) \ + : NULL) + +#define get_config_info(im_info) \ + (im_config_list \ + ? lookup_im_info (im_config_list, (im_info)->language, \ + (im_info)->name, (im_info)->extra) \ + : NULL) + +static int +update_custom_info (void) +{ + MPlist *plist, *pl; + + if (im_custom_mdb) + { + if (mdatabase__check (im_custom_mdb) > 0) + return 1; + } + else + { + MDatabaseInfo *custom_dir_info; + char custom_path[PATH_MAX + 1]; + + custom_dir_info = MPLIST_VAL (mdatabase__dir_list); + if (! custom_dir_info->filename + || custom_dir_info->len + strlen (CUSTOM_FILE) > PATH_MAX) + return -1; + strcpy (custom_path, custom_dir_info->filename); + strcat (custom_path, CUSTOM_FILE); + im_custom_mdb = mdatabase_define (Minput_method, Mt, Mnil, Mconfig, + NULL, custom_path); + } + + if (im_custom_list) + { + free_im_list (im_custom_list); + im_custom_list = NULL; + } + plist = mdatabase_load (im_custom_mdb); + if (! plist) + return -1; + im_custom_list = mplist (); + + MPLIST_DO (pl, plist) + { + MSymbol language, name, extra; + MInputMethodInfo *im_info; + MPlist *im_data, *p; + + if (! MPLIST_PLIST_P (pl)) + continue; + p = MPLIST_PLIST (pl); + im_data = MPLIST_NEXT (p); + if (! MPLIST_PLIST_P (p)) + continue; + p = MPLIST_PLIST (p); + if (! MPLIST_SYMBOL_P (p) + || MPLIST_SYMBOL (p) != Minput_method) + continue; + p = MPLIST_NEXT (p); + if (! MPLIST_SYMBOL_P (p)) + continue; + language = MPLIST_SYMBOL (p); + p = MPLIST_NEXT (p); + if (! MPLIST_SYMBOL_P (p)) + continue; + name = MPLIST_SYMBOL (p); + p = MPLIST_NEXT (p); + if (MPLIST_TAIL_P (p)) + extra = Mnil; + else if (MPLIST_SYMBOL_P (p)) + extra = MPLIST_SYMBOL (p); + if (language == Mnil || (name == Mnil && extra == Mnil)) + continue; + im_info = new_im_info (NULL, language, name, extra, im_custom_list); + load_im_info (im_data, im_info); + } + M17N_OBJECT_UNREF (plist); + return 0; +} + +static int +update_global_info (void) +{ + MPlist *plist; + + if (global_info) + { + int ret = mdatabase__check (global_info->mdb); + + if (ret) + return ret; + fini_im_info (global_info); + } + else + { + MDatabase *mdb = mdatabase_find (Minput_method, Mt, Mnil, Mglobal); + + if (! mdb) + return -1; + global_info = new_im_info (mdb, Mt, Mnil, Mglobal, im_info_list); + } + if (! global_info->mdb + || ! (plist = mdatabase_load (global_info->mdb))) + return -1; + + load_im_info (plist, global_info); + M17N_OBJECT_UNREF (plist); + return 0; +} + + +/* Return an IM_INFO for the input method specified by LANGUAGE, NAME, + and EXTRA. KEY, if not Mnil, tells which kind of information about + the input method is necessary, and the returned IM_INFO may contain + only that information. */ + +static MInputMethodInfo * +get_im_info (MSymbol language, MSymbol name, MSymbol extra, MSymbol key) +{ + MPlist *plist; + MInputMethodInfo *im_info; + MDatabase *mdb; + + if (name == Mnil && extra == Mnil) + language = Mt, extra = Mglobal; + im_info = lookup_im_info (im_info_list, language, name, extra); + if (im_info) + { + if (key == Mnil ? im_info->states != NULL + : key == Mcommand ? im_info->cmds != NULL + : key == Mvariable ? im_info->vars != NULL + : key == Mtitle ? im_info->title != NULL + : key == Mdescription ? im_info->description != NULL + : 1) + /* IM_INFO already contains required information. */ + return im_info; + /* We have not yet loaded required information. */ + } + else + { + mdb = mdatabase_find (Minput_method, language, name, extra); + if (! mdb) + return NULL; + im_info = new_im_info (mdb, language, name, extra, im_info_list); + } + + if (key == Mnil) + { + plist = mdatabase_load (im_info->mdb); + } + else + { + mplist_push (load_im_info_keys, key, Mt); + plist = mdatabase__load_for_keys (im_info->mdb, load_im_info_keys); + mplist_pop (load_im_info_keys); + } + im_info->tick = 0; + if (! plist) + MERROR (MERROR_IM, im_info); + update_global_info (); + load_im_info (plist, im_info); + M17N_OBJECT_UNREF (plist); + if (key == Mnil) + { + if (! im_info->cmds) + im_info->cmds = mplist (); + if (! im_info->vars) + im_info->vars = mplist (); + if (! im_info->states) + im_info->states = mplist (); + } + if (! im_info->title + && (key == Mnil || key == Mtitle)) + im_info->title = (name == Mnil ? mtext () + : mtext_from_data (MSYMBOL_NAME (name), + MSYMBOL_NAMELEN (name), + MTEXT_FORMAT_US_ASCII)); + return im_info; +} + +/* Check if IM_INFO->mdb is updated or not. If not updated, return 0. + If updated, but got unloadable, return -1. Otherwise, update + contents of IM_INFO from the new database, and return 1. */ + +static int +reload_im_info (MInputMethodInfo *im_info) +{ + int check; + MPlist *plist; + + update_custom_info (); + update_global_info (); + check = mdatabase__check (im_info->mdb); + if (check < 0) + return -1; + plist = mdatabase_load (im_info->mdb); + if (! plist) + return -1; + fini_im_info (im_info); + load_im_info (plist, im_info); + M17N_OBJECT_UNREF (plist); + if (! im_info->cmds) + im_info->cmds = mplist (); + if (! im_info->vars) + im_info->vars = mplist (); + if (! im_info->title) + { + MSymbol name = im_info->name; + + im_info->title = (name == Mnil ? mtext () + : mtext_from_data (MSYMBOL_NAME (name), + MSYMBOL_NAMELEN (name), + MTEXT_FORMAT_US_ASCII)); + } + return 1; +} + +static MInputMethodInfo * +get_im_info_by_tags (MPlist *plist) +{ + MSymbol tag[3]; + int i; + + for (i = 0; i < 3 && MPLIST_SYMBOL_P (plist); + i++, plist = MPLIST_NEXT (plist)) + tag[i] = MPLIST_SYMBOL (plist); + if (i < 2) + return NULL; + for (; i < 3; i++) + tag[i] = Mnil; + return get_im_info (tag[0], tag[1], tag[2], Mnil); +} + + +/* Open an input method specified by LANG_NAME, create an input + context for it, and return the input context. */ + + +static MInputContext * +create_ic_for_im (MPlist *lang_name, MInputMethod *current) +{ + MSymbol language, name; + MInputMethod *im; + MInputContext *ic; + MInputDriver *driver = minput_driver; + + language = MPLIST_SYMBOL (lang_name); + lang_name = MPLIST_NEXT (lang_name); + name = MPLIST_SYMBOL (lang_name); + if (language == current->language + && name == current->name) + return NULL; + minput_driver = &minput_default_driver; + im = minput_open_im (language, name, NULL); + if (! im) + { + minput_driver = driver; + return NULL; + } + ic = minput_create_ic (im, NULL); + if (! ic) + { + minput_close_im (im); + minput_driver = driver; + return NULL; + } + minput_driver = driver; + return ic; +} + +static int +check_description (MPlist *plist) +{ + MText *mt; + + if (MPLIST_MTEXT_P (plist)) + return 1; + if (MPLIST_PLIST_P (plist)) + { + MPlist *pl = MPLIST_PLIST (plist); + + if (MFAILP (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == M_gettext)) + return 0; + pl =MPLIST_NEXT (pl); + if (MFAILP (MPLIST_MTEXT_P (pl))) + return 0; + mt = MPLIST_MTEXT (pl); + M17N_OBJECT_REF (mt); +#if ENABLE_NLS + { + char *translated = dgettext ("m17n-db", (char *) MTEXT_DATA (mt)); + + if (translated == (char *) MTEXT_DATA (mt)) + translated = dgettext ("m17n-contrib", (char *) MTEXT_DATA (mt)); + if (translated != (char *) MTEXT_DATA (mt)) + { + M17N_OBJECT_UNREF (mt); + mt = mtext__from_data (translated, strlen (translated), + MTEXT_FORMAT_UTF_8, 1); + } + } +#endif + mplist_set (plist, Mtext, mt); + M17N_OBJECT_UNREF (mt); + return 1; + } + if (MFAILP (MPLIST_SYMBOL_P (plist) && MPLIST_SYMBOL (plist) == Mnil)) + return 0; + return 1; +} + + +/* Check KEYSEQ, and return 1 if it is valid as a key sequence, return + 0 if not. */ + +static int +check_command_keyseq (MPlist *keyseq) +{ + if (MPLIST_PLIST_P (keyseq)) + { + MPlist *p = MPLIST_PLIST (keyseq); + + MPLIST_DO (p, p) + if (! MPLIST_SYMBOL_P (p) && ! MPLIST_INTEGER_P (p)) + return 0; + return 1; + } + if (MPLIST_MTEXT_P (keyseq)) + { + MText *mt = MPLIST_MTEXT (keyseq); + int i; + + for (i = 0; i < mtext_nchars (mt); i++) + if (mtext_ref_char (mt, i) >= 256) + return 0; + return 1; + } + return 0; +} + +/* Load command defitions from PLIST into IM_INFO->cmds. + + PLIST is well-formed and has this form; + (command (NAME [DESCRIPTION KEYSEQ ...]) ...) + NAME is a symbol. DESCRIPTION is an M-text or `nil'. KEYSEQ is an + M-text or a plist of symbols. + + The returned list has the same form, but for each element... + + (1) If DESCRIPTION and the rest are omitted, the element is not + stored in the returned list. + + (2) If DESCRIPTION is nil, it is complemented by the corresponding + description in global_info->cmds (if any). */ + +static void +load_commands (MInputMethodInfo *im_info, MPlist *plist) +{ + MPlist *tail; + + im_info->cmds = tail = mplist (); + + MPLIST_DO (plist, MPLIST_NEXT (plist)) + { + /* PLIST ::= ((NAME DESC KEYSEQ ...) ...) */ + MPlist *pl, *p; + + if (MFAILP (MPLIST_PLIST_P (plist))) + continue; + pl = MPLIST_PLIST (plist); /* PL ::= (NAME DESC KEYSEQ ...) */ + if (MFAILP (MPLIST_SYMBOL_P (pl))) + continue; + p = MPLIST_NEXT (pl); /* P ::= (DESC KEYSEQ ...) */ + if (MPLIST_TAIL_P (p)) /* PL ::= (NAME) */ + { + if (MFAILP (im_info != global_info)) + mplist_add (p, Msymbol, Mnil); /* PL ::= (NAME nil) */ + } + else + { + if (! check_description (p)) + mplist_set (p, Msymbol, Mnil); + p = MPLIST_NEXT (p); + while (! MPLIST_TAIL_P (p)) + { + if (MFAILP (check_command_keyseq (p))) + mplist__pop_unref (p); + else + p = MPLIST_NEXT (p); + } + } + tail = mplist_add (tail, Mplist, pl); + } +} + +static MPlist * +config_command (MPlist *plist, MPlist *global_cmds, MPlist *custom_cmds, + MPlist *config_cmds) +{ + MPlist *global = NULL, *custom = NULL, *config = NULL; + MSymbol name = MPLIST_SYMBOL (plist); + MSymbol status; + MPlist *description, *keyseq; + + if (global_cmds && (global = mplist__assq (global_cmds, name))) + global = MPLIST_NEXT (MPLIST_PLIST (global)); + + plist = MPLIST_NEXT (plist); + if (MPLIST_MTEXT_P (plist) || MPLIST_PLIST_P (plist)) + { + description = plist; + plist = MPLIST_NEXT (plist); + } + else + { + description = global; + if (! MPLIST_TAIL_P (plist)) + plist = MPLIST_NEXT (plist); + } + if (MPLIST_TAIL_P (plist) && global) + { + keyseq = MPLIST_NEXT (global); + status = Minherited; + } + else + { + keyseq = plist; + status = Mnil; + } + + if (config_cmds && (config = mplist__assq (config_cmds, name))) + { + status = Mconfigured; + config = MPLIST_NEXT (MPLIST_PLIST (config)); + if (! MPLIST_TAIL_P (config)) + keyseq = config; + } + else if (custom_cmds && (custom = mplist__assq (custom_cmds, name))) + { + MPlist *this_keyseq = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (custom))); + + if (MPLIST_TAIL_P (this_keyseq)) + mplist__pop_unref (custom); + else + { + status = Mcustomized; + keyseq = this_keyseq; + } + } + + plist = mplist (); + mplist_add (plist, Msymbol, name); + if (description) + mplist_add (plist, MPLIST_KEY (description), MPLIST_VAL (description)); + else + mplist_add (plist, Msymbol, Mnil); + mplist_add (plist, Msymbol, status); + mplist__conc (plist, keyseq); + return plist; +} + +static void +config_all_commands (MInputMethodInfo *im_info) +{ + MPlist *global_cmds, *custom_cmds, *config_cmds; + MInputMethodInfo *temp; + MPlist *tail, *plist; + + M17N_OBJECT_UNREF (im_info->configured_cmds); + + if (MPLIST_TAIL_P (im_info->cmds) + || ! im_info->mdb) + return; + + global_cmds = im_info != global_info ? global_info->cmds : NULL; + custom_cmds = ((temp = get_custom_info (im_info)) ? temp->cmds : NULL); + config_cmds = ((temp = get_config_info (im_info)) ? temp->cmds : NULL); + + im_info->configured_cmds = tail = mplist (); + MPLIST_DO (plist, im_info->cmds) + { + MPlist *pl = config_command (MPLIST_PLIST (plist), + global_cmds, custom_cmds, config_cmds); + if (pl) + { + tail = mplist_add (tail, Mplist, pl); + M17N_OBJECT_UNREF (pl); + } + } +} + +/* Check VAL's value against VALID_VALUES, and return 1 if it is + valid, return 0 if not. */ + +static int +check_variable_value (MPlist *val, MPlist *global) +{ + MSymbol type = MPLIST_KEY (val); + MPlist *valids = MPLIST_NEXT (val); + + if (type != Minteger && type != Mtext && type != Msymbol && type != Mplist) + return 0; + if (global) + { + if (MPLIST_KEY (global) != Mt + && MPLIST_KEY (global) != MPLIST_KEY (val)) + return 0; + if (MPLIST_TAIL_P (valids)) + valids = MPLIST_NEXT (global); + } + if (MPLIST_TAIL_P (valids)) + return 1; + + if (type == Minteger) + { + int n = MPLIST_INTEGER (val); + + MPLIST_DO (valids, valids) + { + if (MPLIST_INTEGER_P (valids)) + { + if (n == MPLIST_INTEGER (valids)) + break; + } + else if (MPLIST_PLIST_P (valids)) + { + MPlist *p = MPLIST_PLIST (valids); + int min_bound, max_bound; + + if (! MPLIST_INTEGER_P (p)) + MERROR (MERROR_IM, 0); + min_bound = MPLIST_INTEGER (p); + p = MPLIST_NEXT (p); + if (! MPLIST_INTEGER_P (p)) + MERROR (MERROR_IM, 0); + max_bound = MPLIST_INTEGER (p); + if (n >= min_bound && n <= max_bound) + break; + } + } + } + else if (type == Msymbol) + { + MSymbol sym = MPLIST_SYMBOL (val); + + MPLIST_DO (valids, valids) + { + if (! MPLIST_SYMBOL_P (valids)) + MERROR (MERROR_IM, 0); + if (sym == MPLIST_SYMBOL (valids)) + break; + } + } + else if (type == Mtext) + { + MText *mt = MPLIST_MTEXT (val); + + MPLIST_DO (valids, valids) + { + if (! MPLIST_MTEXT_P (valids)) + MERROR (MERROR_IM, 0); + if (mtext_cmp (mt, MPLIST_MTEXT (valids)) == 0) + break; + } + } + + return (! MPLIST_TAIL_P (valids)); +} + +/* Load variable definitions from PLIST into IM_INFO->vars. + + PLIST is well-formed and has this form; + ((NAME [DESCRIPTION DEFAULT-VALUE VALID-VALUE ...]) + ...) + NAME is a symbol. DESCRIPTION is an M-text or `nil'. + + The returned list has the same form, but for each element... + + (1) If DESCRIPTION and the rest are omitted, the element is not + stored in the returned list. + + (2) If DESCRIPTION is nil, it is complemented by the corresponding + description in global_info->vars (if any). */ + +static void +load_variables (MInputMethodInfo *im_info, MPlist *plist) +{ + MPlist *global_vars = ((im_info->mdb && im_info != global_info) + ? global_info->vars : NULL); + MPlist *tail; + + im_info->vars = tail = mplist (); + MPLIST_DO (plist, MPLIST_NEXT (plist)) + { + MPlist *pl, *p; + + if (MFAILP (MPLIST_PLIST_P (plist))) + continue; + pl = MPLIST_PLIST (plist); /* PL ::= (NAME DESC VALUE VALID ...) */ + if (MFAILP (MPLIST_SYMBOL_P (pl))) + continue; + if (im_info == global_info) + { + /* Loading a global variable. */ + p = MPLIST_NEXT (pl); + if (MPLIST_TAIL_P (p)) + mplist_add (p, Msymbol, Mnil); + else + { + if (! check_description (p)) + mplist_set (p, Msymbol, Mnil); + p = MPLIST_NEXT (p); + if (MFAILP (! MPLIST_TAIL_P (p) + && check_variable_value (p, NULL))) + mplist_set (p, Mt, NULL); + } + } + else if (im_info->mdb) + { + /* Loading a local variable. */ + MSymbol name = MPLIST_SYMBOL (pl); + MPlist *global = NULL; + + if (global_vars + && (p = mplist__assq (global_vars, name))) + { + /* P ::= ((NAME DESC ...) ...) */ + p = MPLIST_PLIST (p); /* P ::= (NAME DESC ...) */ + global = MPLIST_NEXT (p); /* P ::= (DESC VALUE ...) */ + global = MPLIST_NEXT (global); /* P ::= (VALUE ...) */ + } + + p = MPLIST_NEXT (pl); /* P ::= (DESC VALUE VALID ...) */ + if (! MPLIST_TAIL_P (p)) + { + if (! check_description (p)) + mplist_set (p, Msymbol, Mnil); + p = MPLIST_NEXT (p); /* P ::= (VALUE VALID ...) */ + if (MFAILP (! MPLIST_TAIL_P (p))) + mplist_set (p, Mt, NULL); + else + { + MPlist *valid_values = MPLIST_NEXT (p); + + if (! MPLIST_TAIL_P (valid_values) + ? MFAILP (check_variable_value (p, NULL)) + : global && MFAILP (check_variable_value (p, global))) + mplist_set (p, Mt, NULL); + } + } + } + else + { + /* Loading a variable customization. */ + p = MPLIST_NEXT (pl); /* P ::= (nil VALUE) */ + if (MFAILP (! MPLIST_TAIL_P (p))) + continue; + p = MPLIST_NEXT (p); /* P ::= (VALUE) */ + if (MFAILP (MPLIST_INTEGER_P (p) || MPLIST_SYMBOL_P (p) + || MPLIST_MTEXT_P (p))) + continue; + } + tail = mplist_add (tail, Mplist, pl); + } +} + +static MPlist * +config_variable (MPlist *plist, MPlist *global_vars, MPlist *custom_vars, + MPlist *config_vars) +{ + MPlist *global = NULL, *custom = NULL, *config = NULL; + MSymbol name = MPLIST_SYMBOL (plist); + MSymbol status; + MPlist *description = NULL, *value, *valids; + + if (global_vars) + { + global = mplist__assq (global_vars, name); + if (global) + global = MPLIST_NEXT (MPLIST_PLIST (global)); /* (DESC VALUE ...) */ + } + + plist = MPLIST_NEXT (plist); + if (MPLIST_MTEXT_P (plist) || MPLIST_PLIST_P (plist)) + description = plist; + else if (global) + description = global; + if (global) + global = MPLIST_NEXT (global); /* (VALUE VALIDS ...) */ + + if (MPLIST_TAIL_P (plist)) + { + /* Inherit from global (if any). */ + if (global) + { + value = global; + if (MPLIST_KEY (value) == Mt) + value = NULL; + valids = MPLIST_NEXT (global); + status = Minherited; + } + else + { + value = NULL; + valids = NULL; + status = Mnil; + plist = NULL; + } + } + else + { + value = plist = MPLIST_NEXT (plist); + valids = MPLIST_NEXT (value); + if (MPLIST_KEY (value) == Mt) + value = NULL; + if (! MPLIST_TAIL_P (valids)) + global = NULL; + else if (global) + valids = MPLIST_NEXT (global); + status = Mnil; + } + + if (config_vars && (config = mplist__assq (config_vars, name))) + { + status = Mconfigured; + config = MPLIST_NEXT (MPLIST_PLIST (config)); + if (! MPLIST_TAIL_P (config)) + { + value = config; + if (MFAILP (check_variable_value (value, global ? global : plist))) + value = NULL; + } + } + else if (custom_vars && (custom = mplist__assq (custom_vars, name))) + { + MPlist *this_value = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (custom))); + + if (MPLIST_TAIL_P (this_value)) + mplist__pop_unref (custom); + else + { + value = this_value; + if (MFAILP (check_variable_value (value, global ? global : plist))) + value = NULL; + status = Mcustomized; + } + } + + plist = mplist (); + mplist_add (plist, Msymbol, name); + if (description) + mplist_add (plist, MPLIST_KEY (description), MPLIST_VAL (description)); + else + mplist_add (plist, Msymbol, Mnil); + mplist_add (plist, Msymbol, status); + if (value) + mplist_add (plist, MPLIST_KEY (value), MPLIST_VAL (value)); + else + mplist_add (plist, Mt, NULL); + if (valids && ! MPLIST_TAIL_P (valids)) + mplist__conc (plist, valids); + return plist; +} + +/* Return a configured variable definition list based on + IM_INFO->vars. If a variable in it doesn't contain a value, try to + get it from global_info->vars. */ + +static void +config_all_variables (MInputMethodInfo *im_info) +{ + MPlist *global_vars, *custom_vars, *config_vars; + MInputMethodInfo *temp; + MPlist *tail, *plist; + + M17N_OBJECT_UNREF (im_info->configured_vars); + + if (MPLIST_TAIL_P (im_info->vars) + || ! im_info->mdb) + return; + + global_vars = im_info != global_info ? global_info->vars : NULL; + custom_vars = ((temp = get_custom_info (im_info)) ? temp->vars : NULL); + config_vars = ((temp = get_config_info (im_info)) ? temp->vars : NULL); + + im_info->configured_vars = tail = mplist (); + MPLIST_DO (plist, im_info->vars) + { + MPlist *pl = config_variable (MPLIST_PLIST (plist), + global_vars, custom_vars, config_vars); + if (pl) + { + tail = mplist_add (tail, Mplist, pl); + M17N_OBJECT_UNREF (pl); + } + } +} + +/* Load an input method (LANGUAGE NAME) from PLIST into IM_INFO. + CONFIG contains configuration information of the input method. */ + +static void +load_im_info (MPlist *plist, MInputMethodInfo *im_info) +{ + MPlist *pl, *p; + + if (! im_info->cmds && (pl = mplist__assq (plist, Mcommand))) + { + load_commands (im_info, MPLIST_PLIST (pl)); + config_all_commands (im_info); + pl = mplist_pop (pl); + M17N_OBJECT_UNREF (pl); + } + + if (! im_info->vars && (pl = mplist__assq (plist, Mvariable))) + { + load_variables (im_info, MPLIST_PLIST (pl)); + config_all_variables (im_info); + pl = mplist_pop (pl); + M17N_OBJECT_UNREF (pl); + } + + MPLIST_DO (plist, plist) + if (MPLIST_PLIST_P (plist)) + { + MPlist *elt = MPLIST_PLIST (plist); + MSymbol key; + + if (MFAILP (MPLIST_SYMBOL_P (elt))) + continue; + key = MPLIST_SYMBOL (elt); + if (key == Mtitle) + { + if (im_info->title) + continue; + elt = MPLIST_NEXT (elt); + if (MFAILP (MPLIST_MTEXT_P (elt))) + continue; + im_info->title = MPLIST_MTEXT (elt); + M17N_OBJECT_REF (im_info->title); + } + else if (key == Mmap) + { + pl = mplist__from_alist (MPLIST_NEXT (elt)); + if (MFAILP (pl)) + continue; + if (! im_info->maps) + im_info->maps = pl; + else + { + mplist__conc (im_info->maps, pl); + M17N_OBJECT_UNREF (pl); + } + } + else if (key == Mmacro) + { + if (! im_info->macros) + im_info->macros = mplist (); + MPLIST_DO (elt, MPLIST_NEXT (elt)) + { + if (MFAILP (MPLIST_PLIST_P (elt))) + continue; + load_macros (im_info, MPLIST_PLIST (elt)); + } + } + else if (key == Mmodule) + { + if (! im_info->externals) + im_info->externals = mplist (); + MPLIST_DO (elt, MPLIST_NEXT (elt)) + { + MIMExternalModule *external; + + if (MFAILP (MPLIST_PLIST_P (elt))) + continue; + external = load_external_module (MPLIST_PLIST (elt)); + if (external) + mplist_add (im_info->externals, external->name, external); + } + } + else if (key == Mstate) + { + MPLIST_DO (elt, MPLIST_NEXT (elt)) + { + MIMState *state; + + if (MFAILP (MPLIST_PLIST_P (elt))) + continue; + pl = MPLIST_PLIST (elt); + if (! im_info->states) + im_info->states = mplist (); + state = load_state (im_info, MPLIST_PLIST (elt)); + if (MFAILP (state)) + continue; + mplist_put (im_info->states, state->name, state); + } + } + else if (key == Minclude) + { + /* elt ::= include (tag1 tag2 ...) key item ... */ + MSymbol key; + MInputMethodInfo *temp; + + elt = MPLIST_NEXT (elt); + if (MFAILP (MPLIST_PLIST_P (elt))) + continue; + temp = get_im_info_by_tags (MPLIST_PLIST (elt)); + if (MFAILP (temp)) + continue; + elt = MPLIST_NEXT (elt); + if (MFAILP (MPLIST_SYMBOL_P (elt))) + continue; + key = MPLIST_SYMBOL (elt); + elt = MPLIST_NEXT (elt); + if (key == Mmap) + { + if (! temp->maps || MPLIST_TAIL_P (temp->maps)) + continue; + if (! im_info->maps) + im_info->maps = mplist (); + MPLIST_DO (pl, temp->maps) + { + p = MPLIST_VAL (pl); + MPLIST_ADD_PLIST (im_info->maps, MPLIST_KEY (pl), p); + M17N_OBJECT_REF (p); + } + } + else if (key == Mmacro) + { + if (! temp->macros || MPLIST_TAIL_P (temp->macros)) + continue; + if (! im_info->macros) + im_info->macros = mplist (); + MPLIST_DO (pl, temp->macros) + { + p = MPLIST_VAL (pl); + MPLIST_ADD_PLIST (im_info->macros, MPLIST_KEY (pl), p); + M17N_OBJECT_REF (p); + } + } + else if (key == Mstate) + { + if (! temp->states || MPLIST_TAIL_P (temp->states)) + continue; + if (! im_info->states) + im_info->states = mplist (); + MPLIST_DO (pl, temp->states) + { + MIMState *state = MPLIST_VAL (pl); + + mplist_add (im_info->states, MPLIST_KEY (pl), state); + M17N_OBJECT_REF (state); + } + } + } + else if (key == Mdescription) + { + if (im_info->description) + continue; + elt = MPLIST_NEXT (elt); + if (! check_description (elt)) + continue; + im_info->description = MPLIST_MTEXT (elt); + M17N_OBJECT_REF (im_info->description); + } + } + if (im_info->macros) + { + MPLIST_DO (pl, im_info->macros) + parse_action_list (MPLIST_PLIST (pl), im_info->macros); + } + + im_info->tick = time (NULL); +} + + + +static int take_action_list (MInputContext *ic, MPlist *action_list); +static void preedit_commit (MInputContext *ic, int need_prefix); + +/* Shift to the state of name STATE_NAME. If STATE_NAME is `t', shift + to the previous state (if any). If STATE_NAME is `nil', shift to + the initial state. */ + +static void +shift_state (MInputContext *ic, MSymbol state_name) +{ + MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info; + MInputContextInfo *ic_info = (MInputContextInfo *) ic->info; + MIMState *orig_state = ic_info->state, *state; + + /* Find a state to shift to. If not found, shift to the initial + state. */ + if (state_name == Mt) + { + if (! ic_info->prev_state) + return; + state = ic_info->prev_state; + } + else if (state_name == Mnil) + { + state = (MIMState *) MPLIST_VAL (im_info->states); + } + else + { + state = (MIMState *) mplist_get (im_info->states, state_name); + if (! state) + state = (MIMState *) MPLIST_VAL (im_info->states); + } + + if (MDEBUG_FLAG ()) + { + if (orig_state) + MDEBUG_PRINT4 ("\n [IM:%s-%s] [%s] (shift %s)\n", + MSYMBOL_NAME (im_info->language), + MSYMBOL_NAME (im_info->name), + MSYMBOL_NAME (orig_state->name), + MSYMBOL_NAME (state->name)); + else + MDEBUG_PRINT1 (" (shift %s)\n", MSYMBOL_NAME (state->name)); + } + + /* Enter the new state. */ + ic_info->state = state; + ic_info->map = state->map; + ic_info->state_key_head = ic_info->key_head; + if (state == (MIMState *) MPLIST_VAL (im_info->states) + && orig_state) + /* We have shifted to the initial state. */ + preedit_commit (ic, 0); + mtext_cpy (ic_info->preedit_saved, ic->preedit); + ic_info->state_pos = ic->cursor_pos; + if (state != orig_state || state_name == Mnil) + { + if (state == (MIMState *) MPLIST_VAL (im_info->states)) + { + /* Shifted to the initial state. */ + ic_info->prev_state = NULL; + M17N_OBJECT_UNREF (ic_info->vars_saved); + ic_info->vars_saved = mplist_copy (ic_info->vars); + } + else + ic_info->prev_state = orig_state; + + if (state->title) + ic->status = state->title; + else + ic->status = im_info->title; + ic->status_changed = 1; + ic_info->state_hook = ic_info->map->map_actions; + } +} + +/* Find a candidate group that contains a candidate number INDEX from + PLIST. Set START_INDEX to the first candidate number of the group, + END_INDEX to the last candidate number plus 1, GROUP_INDEX to the + candidate group number if they are non-NULL. If INDEX is -1, find + the last candidate group. */ + +static MPlist * +find_candidates_group (MPlist *plist, int index, + int *start_index, int *end_index, int *group_index) +{ + int i = 0, gidx = 0, len; + + MPLIST_DO (plist, plist) + { + if (MPLIST_MTEXT_P (plist)) + len = mtext_nchars (MPLIST_MTEXT (plist)); + else + len = mplist_length (MPLIST_PLIST (plist)); + if (index < 0 ? MPLIST_TAIL_P (MPLIST_NEXT (plist)) + : i + len > index) + { + if (start_index) + *start_index = i; + if (end_index) + *end_index = i + len; + if (group_index) + *group_index = gidx; + return plist; + } + i += len; + gidx++; + } + return NULL; +} + +/* Adjust markers for the change of preedit text. + If FROM == TO, the change is insertion of INS chars. + If FROM < TO and INS == 0, the change is deletion of the range. + If FROM < TO and INS > 0, the change is replacement. */ + +static void +adjust_markers (MInputContext *ic, int from, int to, int ins) +{ + MInputContextInfo *ic_info = ((MInputContext *) ic)->info; + MPlist *markers; + + if (from == to) + { + MPLIST_DO (markers, ic_info->markers) + if (MPLIST_INTEGER (markers) > from) + MPLIST_VAL (markers) = (void *) (MPLIST_INTEGER (markers) + ins); + if (ic->cursor_pos >= from) + ic->cursor_pos += ins; + } + else + { + MPLIST_DO (markers, ic_info->markers) + { + if (MPLIST_INTEGER (markers) >= to) + MPLIST_VAL (markers) + = (void *) (MPLIST_INTEGER (markers) + ins - (to - from)); + else if (MPLIST_INTEGER (markers) > from) + MPLIST_VAL (markers) = (void *) from; + } + if (ic->cursor_pos >= to) + ic->cursor_pos += ins - (to - from); + else if (ic->cursor_pos > from) + ic->cursor_pos = from; + } +} + + +static void +preedit_insert (MInputContext *ic, int pos, MText *mt, int c) +{ + int nchars = mt ? mtext_nchars (mt) : 1; + + if (mt) + { + mtext_ins (ic->preedit, pos, mt); + MDEBUG_PRINT1 ("(\"%s\")", MTEXT_DATA (mt)); + } + else + { + mtext_ins_char (ic->preedit, pos, c, 1); + if (c < 0x7F) + MDEBUG_PRINT1 ("('%c')", c); + else + MDEBUG_PRINT1 ("(U+%04X)", c); + } + adjust_markers (ic, pos, pos, nchars); + ic->preedit_changed = 1; +} + + +static void +preedit_delete (MInputContext *ic, int from, int to) +{ + mtext_del (ic->preedit, from, to); + adjust_markers (ic, from, to, 0); + ic->preedit_changed = 1; +} + +static void +preedit_replace (MInputContext *ic, int from, int to, MText *mt, int c) +{ + int ins; + + mtext_del (ic->preedit, from, to); + if (mt) + { + mtext_ins (ic->preedit, from, mt); + ins = mtext_nchars (mt); + } + else + { + mtext_ins_char (ic->preedit, from, c, 1); + ins = 1; + } + adjust_markers (ic, from, to, ins); + ic->preedit_changed = 1; +} + + +static void +preedit_commit (MInputContext *ic, int need_prefix) +{ + MInputContextInfo *ic_info = (MInputContextInfo *) ic->info; + int preedit_len = mtext_nchars (ic->preedit); + + if (preedit_len > 0) + { + MPlist *p; + + mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit), + Mcandidate_list, NULL, 0); + mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit), + Mcandidate_index, NULL, 0); + mtext_cat (ic->produced, ic->preedit); + if (MDEBUG_FLAG ()) + { + int i; + + if (need_prefix) + { + MInputMethodInfo *im_info = ic->im->info; + MDEBUG_PRINT3 ("\n [IM:%s-%s] [%s]", + MSYMBOL_NAME (im_info->language), + MSYMBOL_NAME (im_info->name), + MSYMBOL_NAME (ic_info->state->name)); + } + MDEBUG_PRINT (" (commit"); + for (i = 0; i < mtext_nchars (ic->preedit); i++) + MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->preedit, i)); + MDEBUG_PRINT (")"); + } + + mtext_reset (ic->preedit); + mtext_reset (ic_info->preedit_saved); + MPLIST_DO (p, ic_info->markers) + MPLIST_VAL (p) = 0; + ic->cursor_pos = ic_info->state_pos = 0; + ic->preedit_changed = 1; + ic_info->commit_key_head = ic_info->key_head; + } + if (ic->candidate_list) + { + M17N_OBJECT_UNREF (ic->candidate_list); + ic->candidate_list = NULL; + ic->candidate_index = 0; + ic->candidate_from = ic->candidate_to = 0; + ic->candidates_changed = MINPUT_CANDIDATES_LIST_CHANGED; + if (ic->candidate_show) + { + ic->candidate_show = 0; + ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED; + } + } +} + +static int +new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt) +{ + int code = marker_code (sym, 0); + + if (mt && (code == '[' || code == ']')) + { + int pos = current; + + if (code == '[' && current > 0) + { + if (mtext_prop_range (mt, Mcandidate_list, pos - 1, &pos, NULL, 1) + && pos > 0) + current = pos; + } + else if (code == ']' && current < mtext_nchars (mt)) + { + if (mtext_prop_range (mt, Mcandidate_list, pos, NULL, &pos, 1)) + current = pos; + } + return current; + } + if (code >= 0) + return (code == '<' ? 0 + : code == '>' ? limit + : code == '-' ? current - 1 + : code == '+' ? current + 1 + : code == '=' ? current + : code - '0' > limit ? limit + : code - '0'); + if (! ic) + return 0; + return (int) mplist_get (((MInputContextInfo *) ic->info)->markers, sym); +} + +static void +update_candidate (MInputContext *ic, MTextProperty *prop, int idx) +{ + int from = mtext_property_start (prop); + int to = mtext_property_end (prop); + int start; + MPlist *candidate_list = mtext_property_value (prop); + MPlist *group = find_candidates_group (candidate_list, idx, &start, + NULL, NULL); + int ingroup_index = idx - start; + MText *mt; + + candidate_list = mplist_copy (candidate_list); + if (MPLIST_MTEXT_P (group)) + { + mt = MPLIST_MTEXT (group); + preedit_replace (ic, from, to, NULL, mtext_ref_char (mt, ingroup_index)); + to = from + 1; + } + else + { + int i; + MPlist *plist; + + for (i = 0, plist = MPLIST_PLIST (group); i < ingroup_index; + i++, plist = MPLIST_NEXT (plist)); + mt = MPLIST_MTEXT (plist); + preedit_replace (ic, from, to, mt, 0); + to = from + mtext_nchars (mt); + } + mtext_put_prop (ic->preedit, from, to, Mcandidate_list, candidate_list); + M17N_OBJECT_UNREF (candidate_list); + mtext_put_prop (ic->preedit, from, to, Mcandidate_index, (void *) idx); + ic->cursor_pos = to; +} + +static MCharset * +get_select_charset (MInputContextInfo * ic_info) +{ + MPlist *plist = resolve_variable (ic_info, Mcandidates_charset); + MSymbol sym; + + if (! MPLIST_VAL (plist)) + return NULL; + sym = MPLIST_SYMBOL (plist); + if (sym == Mnil) + return NULL; + return MCHARSET (sym); +} + +/* The returned plist must be UNREFed. */ + +static MPlist * +adjust_candidates (MPlist *plist, MCharset *charset) +{ + MPlist *pl; + + /* plist ::= MTEXT ... | PLIST ... */ + plist = mplist_copy (plist); + if (MPLIST_MTEXT_P (plist)) + { + pl = plist; + while (! MPLIST_TAIL_P (pl)) + { + /* pl ::= MTEXT ... */ + MText *mt = MPLIST_MTEXT (pl); + int mt_copied = 0; + int i, c; + + for (i = mtext_nchars (mt) - 1; i >= 0; i--) + { + c = mtext_ref_char (mt, i); + if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE) + { + if (! mt_copied) + { + mt = mtext_dup (mt); + mplist_set (pl, Mtext, mt); + M17N_OBJECT_UNREF (mt); + mt_copied = 1; + } + mtext_del (mt, i, i + 1); + } + } + if (mtext_len (mt) > 0) + pl = MPLIST_NEXT (pl); + else + { + mplist_pop (pl); + M17N_OBJECT_UNREF (mt); + } + } + } + else /* MPLIST_PLIST_P (plist) */ + { + pl = plist; + while (! MPLIST_TAIL_P (pl)) + { + /* pl ::= (MTEXT ...) ... */ + MPlist *p = MPLIST_PLIST (pl); + int p_copied = 0; + /* p ::= MTEXT ... */ + MPlist *p0 = p; + int n = 0; + + while (! MPLIST_TAIL_P (p0)) + { + MText *mt = MPLIST_MTEXT (p0); + int i, c; + + for (i = mtext_nchars (mt) - 1; i >= 0; i--) + { + c = mtext_ref_char (mt, i); + if (ENCODE_CHAR (charset, c) == MCHAR_INVALID_CODE) + break; + } + if (i < 0) + { + p0 = MPLIST_NEXT (p0); + n++; + } + else + { + if (! p_copied) + { + p = mplist_copy (p); + mplist_set (pl, Mplist, p); + M17N_OBJECT_UNREF (p); + p_copied = 1; + p0 = p; + while (n-- > 0) + p0 = MPLIST_NEXT (p0); + } + mplist_pop (p0); + M17N_OBJECT_UNREF (mt); + } + } + if (! MPLIST_TAIL_P (p)) + pl = MPLIST_NEXT (pl); + else + { + mplist_pop (pl); + M17N_OBJECT_UNREF (p); + } + } + } + if (MPLIST_TAIL_P (plist)) + { + M17N_OBJECT_UNREF (plist); + return NULL; + } + return plist; +} + +/* The returned Plist must be UNREFed. */ + +static MPlist * +get_candidate_list (MInputContextInfo *ic_info, MPlist *args) +{ + MCharset *charset = get_select_charset (ic_info); + MPlist *plist; + int column; + int i, len; + + plist = resolve_variable (ic_info, Mcandidates_group_size); + column = MPLIST_INTEGER (plist); + + plist = MPLIST_PLIST (args); + if (! plist) + return NULL; + if (charset) + { + plist = adjust_candidates (plist, charset); + if (! plist) + return NULL; + } + else + M17N_OBJECT_REF (plist); + + if (column == 0) + return plist; + + if (MPLIST_MTEXT_P (plist)) + { + MText *mt = MPLIST_MTEXT (plist); + MPlist *next = MPLIST_NEXT (plist); + + if (MPLIST_TAIL_P (next)) + M17N_OBJECT_REF (mt); + else + { + mt = mtext_dup (mt); + while (! MPLIST_TAIL_P (next)) + { + mt = mtext_cat (mt, MPLIST_MTEXT (next)); + next = MPLIST_NEXT (next); + } + } + M17N_OBJECT_UNREF (plist); + plist = mplist (); + len = mtext_nchars (mt); + if (len <= column) + mplist_add (plist, Mtext, mt); + else + { + for (i = 0; i < len; i += column) + { + int to = (i + column < len ? i + column : len); + MText *sub = mtext_copy (mtext (), 0, mt, i, to); + + mplist_add (plist, Mtext, sub); + M17N_OBJECT_UNREF (sub); + } + } + M17N_OBJECT_UNREF (mt); + } + else if (MPLIST_PLIST_P (plist)) + { + MPlist *tail = plist; + MPlist *new = mplist (); + MPlist *this = mplist (); + int count = 0; + + MPLIST_DO (tail, tail) + { + MPlist *p = MPLIST_PLIST (tail); + + MPLIST_DO (p, p) + { + MText *mt = MPLIST_MTEXT (p); + + if (count == column) + { + mplist_add (new, Mplist, this); + M17N_OBJECT_UNREF (this); + this = mplist (); + count = 0; + } + mplist_add (this, Mtext, mt); + count++; + } + } + mplist_add (new, Mplist, this); + M17N_OBJECT_UNREF (this); + mplist_set (plist, Mnil, NULL); + MPLIST_DO (tail, new) + { + MPlist *elt = MPLIST_PLIST (tail); + + mplist_add (plist, Mplist, elt); + } + M17N_OBJECT_UNREF (new); + } + + return plist; +} + + +static MPlist * +regularize_action (MPlist *action_list, MInputContextInfo *ic_info) +{ + MPlist *action = NULL; + MSymbol name; + MPlist *args; + + if (MPLIST_SYMBOL_P (action_list)) + { + MSymbol var = MPLIST_SYMBOL (action_list); + MPlist *p; + + MPLIST_DO (p, ic_info->vars) + if (MPLIST_SYMBOL (MPLIST_PLIST (p)) == var) + break; + if (MPLIST_TAIL_P (p)) + return NULL; + action = MPLIST_NEXT (MPLIST_PLIST (p)); + mplist_set (action_list, MPLIST_KEY (action), MPLIST_VAL (action)); + } + + if (MPLIST_PLIST_P (action_list)) + { + action = MPLIST_PLIST (action_list); + if (MPLIST_SYMBOL_P (action)) + { + name = MPLIST_SYMBOL (action); + args = MPLIST_NEXT (action); + if (name == Minsert + && MPLIST_PLIST_P (args)) + mplist_set (action, Msymbol, M_candidates); + } + else if (MPLIST_MTEXT_P (action) || MPLIST_PLIST_P (action)) + { + action = mplist (); + mplist_push (action, Mplist, MPLIST_VAL (action_list)); + mplist_push (action, Msymbol, M_candidates); + mplist_set (action_list, Mplist, action); + M17N_OBJECT_UNREF (action); + } + } + else if (MPLIST_MTEXT_P (action_list) || MPLIST_INTEGER_P (action_list)) + { + action = mplist (); + mplist_push (action, MPLIST_KEY (action_list), MPLIST_VAL (action_list)); + mplist_push (action, Msymbol, Minsert); + mplist_set (action_list, Mplist, action); + M17N_OBJECT_UNREF (action); + } + return action; +} + +/* Perform list of actions in ACTION_LIST for the current input + context IC. If "unhandle" action was performed or an error + occurred, return -1. Otherwise, return 0, 1, 2, or 3. See the + comment in filter () for the detail. */ + +static int +take_action_list (MInputContext *ic, MPlist *action_list) +{ + MInputContextInfo *ic_info = (MInputContextInfo *) ic->info; + MTextProperty *prop; + int result; + + MPLIST_DO (action_list, action_list) + { + MPlist *action = regularize_action (action_list, ic_info); + MSymbol name; + MPlist *args; + + if (! action) + continue; + name = MPLIST_SYMBOL (action); + args = MPLIST_NEXT (action); + + MDEBUG_PRINT1 (" %s", MSYMBOL_NAME (name)); + if (name == Minsert) + { + if (MPLIST_SYMBOL_P (args)) + { + args = resolve_variable (ic_info, MPLIST_SYMBOL (args)); + if (! MPLIST_MTEXT_P (args) && ! MPLIST_INTEGER_P (args)) + continue; + } + if (MPLIST_MTEXT_P (args)) + preedit_insert (ic, ic->cursor_pos, MPLIST_MTEXT (args), 0); + else /* MPLIST_INTEGER_P (args)) */ + preedit_insert (ic, ic->cursor_pos, NULL, MPLIST_INTEGER (args)); + } + else if (name == M_candidates) + { + MPlist *plist = get_candidate_list (ic_info, args); + MPlist *pl; + int len; + + if (! plist) + continue; + if (MPLIST_PLIST_P (plist) && MPLIST_TAIL_P (plist)) + { + M17N_OBJECT_UNREF (plist); + continue; + } + if (MPLIST_MTEXT_P (plist)) + { + preedit_insert (ic, ic->cursor_pos, NULL, + mtext_ref_char (MPLIST_MTEXT (plist), 0)); + len = 1; + } + else + { + MText * mt = MPLIST_MTEXT (MPLIST_PLIST (plist)); + + preedit_insert (ic, ic->cursor_pos, mt, 0); + len = mtext_nchars (mt); + } + pl = mplist_copy (plist); + M17N_OBJECT_UNREF (plist); + mtext_put_prop (ic->preedit, + ic->cursor_pos - len, ic->cursor_pos, + Mcandidate_list, pl); + M17N_OBJECT_UNREF (pl); + mtext_put_prop (ic->preedit, + ic->cursor_pos - len, ic->cursor_pos, + Mcandidate_index, (void *) 0); + } + else if (name == Mselect) + { + int start, end; + int code, idx, gindex; + int pos = ic->cursor_pos; + MPlist *group; + int idx_decided = 0; + + if (pos == 0 + || ! (prop = mtext_get_property (ic->preedit, pos - 1, + Mcandidate_list))) + continue; + idx = (int) mtext_get_prop (ic->preedit, pos - 1, Mcandidate_index); + group = find_candidates_group (mtext_property_value (prop), idx, + &start, &end, &gindex); + if (MPLIST_SYMBOL_P (args)) + { + code = marker_code (MPLIST_SYMBOL (args), 0); + if (code < 0) + { + args = resolve_variable (ic_info, MPLIST_SYMBOL (args)); + if (! MPLIST_INTEGER_P (args)) + continue; + idx = start + MPLIST_INTEGER (args); + if (idx < start || idx >= end) + continue; + idx_decided = 1; + } + } + else + code = -1; + + if (code != '[' && code != ']') + { + if (! idx_decided) + idx = (start + + (code >= 0 + ? new_index (NULL, ic->candidate_index - start, + end - start - 1, MPLIST_SYMBOL (args), + NULL) + : MPLIST_INTEGER (args))); + if (idx < 0) + { + find_candidates_group (mtext_property_value (prop), -1, + NULL, &end, NULL); + idx = end - 1; + } + else if (idx >= end + && MPLIST_TAIL_P (MPLIST_NEXT (group))) + idx = 0; + } + else + { + int ingroup_index = idx - start; + int len; + + group = mtext_property_value (prop); + len = mplist_length (group); + if (code == '[') + { + gindex--; + if (gindex < 0) + gindex = len - 1;; + } + else + { + gindex++; + if (gindex >= len) + gindex = 0; + } + for (idx = 0; gindex > 0; gindex--, group = MPLIST_NEXT (group)) + idx += (MPLIST_MTEXT_P (group) + ? mtext_nchars (MPLIST_MTEXT (group)) + : mplist_length (MPLIST_PLIST (group))); + len = (MPLIST_MTEXT_P (group) + ? mtext_nchars (MPLIST_MTEXT (group)) + : mplist_length (MPLIST_PLIST (group))); + if (ingroup_index >= len) + ingroup_index = len - 1; + idx += ingroup_index; + } + update_candidate (ic, prop, idx); + MDEBUG_PRINT1 ("(%d)", idx); + } + else if (name == Mshow) + ic->candidate_show = 1; + else if (name == Mhide) + ic->candidate_show = 0; + else if (name == Mdelete) + { + int len = mtext_nchars (ic->preedit); + int pos; + int to; + + if (MPLIST_SYMBOL_P (args) + && surrounding_pos (MPLIST_SYMBOL (args), &pos)) + { + to = ic->cursor_pos + pos; + if (to < 0) + { + delete_surrounding_text (ic, to); + to = 0; + } + else if (to > len) + { + delete_surrounding_text (ic, to - len); + to = len; + } + } + else + { + to = (MPLIST_SYMBOL_P (args) + ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args), + ic->preedit) + : MPLIST_INTEGER (args)); + if (to < 0) + to = 0; + else if (to > len) + to = len; + pos = to - ic->cursor_pos; + } + MDEBUG_PRINT1 ("(%d)", pos); + if (to < ic->cursor_pos) + preedit_delete (ic, to, ic->cursor_pos); + else if (to > ic->cursor_pos) + preedit_delete (ic, ic->cursor_pos, to); + } + else if (name == Mmove) + { + int len = mtext_nchars (ic->preedit); + int pos + = (MPLIST_SYMBOL_P (args) + ? new_index (ic, ic->cursor_pos, len, MPLIST_SYMBOL (args), + ic->preedit) + : MPLIST_INTEGER (args)); + + if (pos < 0) + pos = 0; + else if (pos > len) + pos = len; + if (pos != ic->cursor_pos) + { + ic->cursor_pos = pos; + ic->preedit_changed = 1; + } + MDEBUG_PRINT1 ("(%d)", ic->cursor_pos); + } + else if (name == Mmark) + { + int code = marker_code (MPLIST_SYMBOL (args), 0); + + if (code < 0) + { + mplist_put (ic_info->markers, MPLIST_SYMBOL (args), + (void *) ic->cursor_pos); + MDEBUG_PRINT1 ("(%d)", ic->cursor_pos); + } + } + else if (name == Mpushback) + { + if (MPLIST_INTEGER_P (args) || MPLIST_SYMBOL_P (args)) + { + int num; + + if (MPLIST_SYMBOL_P (args)) + { + args = resolve_variable (ic_info, MPLIST_SYMBOL (args)); + if (MPLIST_INTEGER_P (args)) + num = MPLIST_INTEGER (args); + else + num = 0; + } + else + num = MPLIST_INTEGER (args); + + if (num > 0) + ic_info->key_head -= num; + else if (num == 0) + ic_info->key_head = 0; + else + ic_info->key_head = - num; + if (ic_info->key_head > ic_info->used) + ic_info->key_head = ic_info->used; + } + else if (MPLIST_MTEXT_P (args)) + { + MText *mt = MPLIST_MTEXT (args); + int i, len = mtext_nchars (mt); + MSymbol key; + + ic_info->key_head--; + for (i = 0; i < len; i++) + { + key = one_char_symbol[MTEXT_DATA (mt)[i]]; + if (ic_info->key_head + i < ic_info->used) + ic_info->keys[ic_info->key_head + i] = key; + else + MLIST_APPEND1 (ic_info, keys, key, MERROR_IM); + } + } + else + { + MPlist *plist = MPLIST_PLIST (args), *pl; + int i = 0; + MSymbol key; + + ic_info->key_head--; + + MPLIST_DO (pl, plist) + { + key = MPLIST_SYMBOL (pl); + if (ic_info->key_head < ic_info->used) + ic_info->keys[ic_info->key_head + i] = key; + else + MLIST_APPEND1 (ic_info, keys, key, MERROR_IM); + i++; + } + } + } + else if (name == Mpop) + { + if (ic_info->key_head < ic_info->used) + MLIST_DELETE1 (ic_info, keys, ic_info->key_head, 1); + } + else if (name == Mcall) + { + MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info; + MIMExternalFunc func = NULL; + MSymbol module, func_name; + MPlist *func_args, *val; + + result = 0; + module = MPLIST_SYMBOL (args); + args = MPLIST_NEXT (args); + func_name = MPLIST_SYMBOL (args); + + if (im_info->externals) + { + MIMExternalModule *external + = (MIMExternalModule *) mplist_get (im_info->externals, + module); + if (external) + func = ((MIMExternalFunc) + mplist_get_func (external->func_list, func_name)); + } + if (! func) + continue; + func_args = mplist (); + mplist_add (func_args, Mt, ic); + MPLIST_DO (args, MPLIST_NEXT (args)) + { + int code; + + if (MPLIST_KEY (args) == Msymbol + && MPLIST_KEY (args) != Mnil + && (code = marker_code (MPLIST_SYMBOL (args), 0)) >= 0) + { + code = new_index (ic, ic->cursor_pos, + mtext_nchars (ic->preedit), + MPLIST_SYMBOL (args), ic->preedit); + mplist_add (func_args, Minteger, (void *) code); + } + else + mplist_add (func_args, MPLIST_KEY (args), MPLIST_VAL (args)); + } + val = (func) (func_args); + M17N_OBJECT_UNREF (func_args); + if (val && ! MPLIST_TAIL_P (val)) + result = take_action_list (ic, val); + M17N_OBJECT_UNREF (val); + if (result != 0) + return result; + } + else if (name == Mshift) + { + shift_state (ic, MPLIST_SYMBOL (args)); + } + else if (name == Mundo) + { + int intarg = (MPLIST_TAIL_P (args) + ? ic_info->used - 2 + : integer_value (ic, args, 0)); + + mtext_reset (ic->preedit); + mtext_reset (ic_info->preedit_saved); + mtext_reset (ic->produced); + M17N_OBJECT_UNREF (ic_info->vars); + ic_info->vars = mplist_copy (ic_info->vars_saved); + ic->cursor_pos = ic_info->state_pos = 0; + ic_info->state_key_head = ic_info->key_head + = ic_info->commit_key_head = 0; + + shift_state (ic, Mnil); + if (intarg < 0) + { + if (MPLIST_TAIL_P (args)) + { + ic_info->used = 0; + return -1; + } + ic_info->used += intarg; + } + else + ic_info->used = intarg; + break; + } + else if (name == Mset || name == Madd || name == Msub + || name == Mmul || name == Mdiv) + { + MSymbol sym = MPLIST_SYMBOL (args); + MPlist *value = resolve_variable (ic_info, sym); + int val1, val2; + char *op; + + val1 = MPLIST_INTEGER (value); + args = MPLIST_NEXT (args); + val2 = resolve_expression (ic, args); + if (name == Mset) + val1 = val2, op = "="; + else if (name == Madd) + val1 += val2, op = "+="; + else if (name == Msub) + val1 -= val2, op = "-="; + else if (name == Mmul) + val1 *= val2, op = "*="; + else + val1 /= val2, op = "/="; + MDEBUG_PRINT4 ("(%s %s 0x%X(%d))", + MSYMBOL_NAME (sym), op, val1, val1); + mplist_set (value, Minteger, (void *) val1); + } + else if (name == Mequal || name == Mless || name == Mgreater + || name == Mless_equal || name == Mgreater_equal) + { + int val1, val2; + MPlist *actions1, *actions2; + + val1 = resolve_expression (ic, args); + args = MPLIST_NEXT (args); + val2 = resolve_expression (ic, args); + args = MPLIST_NEXT (args); + actions1 = MPLIST_PLIST (args); + args = MPLIST_NEXT (args); + if (MPLIST_TAIL_P (args)) + actions2 = NULL; + else + actions2 = MPLIST_PLIST (args); + MDEBUG_PRINT3 ("(%d %s %d)? ", val1, MSYMBOL_NAME (name), val2); + if (name == Mequal ? val1 == val2 + : name == Mless ? val1 < val2 + : name == Mgreater ? val1 > val2 + : name == Mless_equal ? val1 <= val2 + : val1 >= val2) + { + MDEBUG_PRINT ("ok"); + result = take_action_list (ic, actions1); + } + else + { + MDEBUG_PRINT ("no"); + if (actions2) + result = take_action_list (ic, actions2); + } + if (result != 0) + return result; + } + else if (name == Mcond) + { + int idx = 0; + + MPLIST_DO (args, args) + { + MPlist *cond; + + idx++; + if (! MPLIST_PLIST (args)) + continue; + cond = MPLIST_PLIST (args); + if (resolve_expression (ic, cond) != 0) + { + MDEBUG_PRINT1 ("(%dth)", idx); + result = take_action_list (ic, MPLIST_NEXT (cond)); + if (result != 0) + return result; + break; + } + } + } + else if (name == Mcommit) + { + preedit_commit (ic, 0); + } + else if (name == Munhandle) + { + preedit_commit (ic, 0); + return -1; + } + else if (name == Mswitch_im) + { + ic_info->pushing_or_switching = args; + M17N_OBJECT_REF (args); + return 1; + } + else if (name == Mpush_im) + { + ic_info->pushing_or_switching = args; + M17N_OBJECT_REF (args); + return 2; + } + else if (name == Mpop_im) + { + shift_state (ic, Mnil); + return 3; + } + else + { + MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info; + MPlist *actions; + + if (im_info->macros + && (actions = mplist_get (im_info->macros, name))) + { + result = take_action_list (ic, actions); + if (result != 0) + return result; + }; + } + } + return 0; +} + + +/* Handle the input key KEY in the current state and map specified in + the input context IC. If KEY was handled correctly, return 0 + (without im switching) or a positive number (with im switching). + Otherwise, return -1. */ + +static int +handle_key (MInputContext *ic) +{ + MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info; + MInputContextInfo *ic_info = (MInputContextInfo *) ic->info; + MIMMap *map = ic_info->map; + MIMMap *submap = NULL; + MSymbol key = ic_info->keys[ic_info->key_head]; + MSymbol alias = Mnil; + int result; + int i; + + if (ic_info->state_hook) + { + MDEBUG_PRINT3 (" [IM:%s-%s] [%s] init-actions:", + MSYMBOL_NAME (im_info->language), + MSYMBOL_NAME (im_info->name), + MSYMBOL_NAME (ic_info->state->name)); + result = take_action_list (ic, ic_info->state_hook); + mtext_cpy (ic_info->preedit_saved, ic->preedit); + ic_info->state_pos = ic->cursor_pos; + ic_info->state_hook = NULL; + if (result != 0) + { + MDEBUG_PRINT ("\n"); + return result; + } + } + + MDEBUG_PRINT4 (" [IM:%s-%s] [%s] handle `%s'", + MSYMBOL_NAME (im_info->language), + MSYMBOL_NAME (im_info->name), + MSYMBOL_NAME (ic_info->state->name), msymbol_name (key)); + + if (map->submaps) + { + submap = mplist_get (map->submaps, key); + alias = key; + while (! submap + && (alias = msymbol_get (alias, M_key_alias)) + && alias != key) + submap = mplist_get (map->submaps, alias); + } + + if (submap) + { + if (! alias || alias == key) + MDEBUG_PRINT (" submap-found"); + else + MDEBUG_PRINT1 (" submap-found (by alias `%s')", MSYMBOL_NAME (alias)); + mtext_cpy (ic->preedit, ic_info->preedit_saved); + ic->preedit_changed = 1; + ic->cursor_pos = ic_info->state_pos; + ic_info->key_head++; + ic_info->map = map = submap; + if (map->map_actions) + { + MDEBUG_PRINT (" map-actions:"); + result = take_action_list (ic, map->map_actions); + if (result != 0) + { + MDEBUG_PRINT ("\n"); + return result; + } + } + else if (map->submaps) + { + for (i = ic_info->state_key_head; i < ic_info->key_head; i++) + { + MSymbol key = ic_info->keys[i]; + char *name = msymbol_name (key); + + if (! name[0] || ! name[1]) + mtext_ins_char (ic->preedit, ic->cursor_pos++, name[0], 1); + } + } + + /* If this is the terminal map or we have shifted to another + state, perform branch actions (if any). */ + if (! map->submaps || map != ic_info->map) + { + if (map->branch_actions) + { + MDEBUG_PRINT (" branch-actions:"); + result = take_action_list (ic, map->branch_actions); + if (result != 0) + { + MDEBUG_PRINT ("\n"); + return result; + } + } + /* If MAP is still not the root map, shift to the current + state. */ + if (ic_info->map != ic_info->state->map) + shift_state (ic, ic_info->state->name); + } + } + else + { + /* MAP can not handle KEY. */ + + /* Perform branch actions if any. */ + if (map->branch_actions) + { + MDEBUG_PRINT (" branch-actions:"); + result = take_action_list (ic, map->branch_actions); + if (result != 0) + { + MDEBUG_PRINT ("\n"); + return result; + } + } + + if (map == ic_info->map) + { + /* The above branch actions didn't change the state. */ + + /* If MAP is the root map of the initial state, and there + still exist an unhandled key, it means that the current + input method can not handle it. */ + if (map == ((MIMState *) MPLIST_VAL (im_info->states))->map + && ic_info->key_head < ic_info->used) + { + MDEBUG_PRINT (" unhandled\n"); + ic_info->state_hook = map->map_actions; + return -1; + } + + if (map != ic_info->state->map) + { + /* MAP is not the root map. Shift to the root map of the + current state. */ + shift_state (ic, ic_info->state->name); + } + else if (! map->branch_actions) + { + /* MAP is the root map without any default branch + actions. Shift to the initial state. */ + shift_state (ic, Mnil); + } + } + } + MDEBUG_PRINT ("\n"); + return 0; +} + +struct MIMInputStack +{ + MInputMethodInfo *im_info; + MInputContextInfo *ic_info; +}; + +static void +pop_im (MInputContext *ic) +{ + MInputContextInfo *ic_info = (MInputContextInfo *) ic->info; + MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info; + int i; + + shift_state (ic, Mnil); + for (i = 0; i < ic_info->used; i++) + MLIST_APPEND1 (ic_info->stack->ic_info, keys, ic_info->keys[i], MERROR_IM); + ic_info->stack->ic_info->key_head = 0; + ic_info->stack->ic_info->state_key_head = 0; + ic_info->stack->ic_info->commit_key_head = 0; + ic_info->stack->ic_info->used = ic_info->used; + ic_info->used = ic_info->key_head + = ic_info->state_key_head = ic_info->commit_key_head = 0; + + MDEBUG_PRINT2 ("\n [IM:%s-%s] poped", + MSYMBOL_NAME (im_info->language), + MSYMBOL_NAME (im_info->name)); + ic->im->info = ic_info->stack->im_info; + ic->info = ic_info->stack->ic_info; + /*ic_info = (MInputContextInfo *) ic->info;*/ + free (ic_info->stack); + ic_info->stack = NULL; + ic->status = ((MInputMethodInfo *) (ic->im->info))->title; + ic->status_changed = ic->preedit_changed = ic->candidates_changed = 1; +} + +static MInputContextInfo * +push_im (MInputContext *ic, MInputContext *pushing) +{ + MInputContextInfo *ic_info = (MInputContextInfo *) ic->info; + MInputContextInfo *new_info; + MIMInputStack *stack; + MText *produced; + int i; + + if (! pushing) + { + pushing = create_ic_for_im (ic_info->pushing_or_switching, ic->im); + if (! pushing) + { + free (stack); + MERROR (MERROR_IM, NULL); + } + } + + new_info = pushing->info; + for (i = 0; i < ic_info->used; i++) + MLIST_APPEND1 (new_info, keys, ic_info->keys[i], MERROR_IM); + new_info->key_head = 0; + new_info->state_key_head = 0; + new_info->commit_key_head = 0; + ic_info->used = 0; + ic_info->key_head = ic_info->state_key_head = ic_info->commit_key_head = 0; + MSTRUCT_CALLOC_SAFE (stack); + if (! stack) + MERROR (MERROR_IM, NULL); + stack->im_info = (MInputMethodInfo *)ic->im->info; + stack->ic_info = ic_info; + M17N_OBJECT_UNREF (ic_info->pushing_or_switching); + ic->im->info = pushing->im->info; + ic->info = pushing->info; + ic->status = pushing->status; + ic->status_changed = 1; + ic_info = (MInputContextInfo *) ic->info; + ic_info->stack = stack; + MDEBUG_PRINT2 ("\n [IM:%s-%s] pushed", + MSYMBOL_NAME (pushing->im->language), + MSYMBOL_NAME (pushing->im->name)); + return ic_info; +} + +/* Initialize IC->ic_info of which members are all zero cleared now. */ + +static void +init_ic_info (MInputContext *ic) +{ + MInputMethodInfo *im_info = ic->im->info; + MInputContextInfo *ic_info = ic->info; + MPlist *plist; + + MLIST_INIT1 (ic_info, keys, 8);; + + ic_info->markers = mplist (); + + ic_info->vars = mplist (); + /* If this input method has its own setting of variables, record + those values in ic_info->vars. */ + if (im_info->configured_vars) + MPLIST_DO (plist, im_info->configured_vars) + { + MPlist *pl = MPLIST_PLIST (plist); + MSymbol name = MPLIST_SYMBOL (pl); + + pl = MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (pl))); + if (MPLIST_KEY (pl) != Mt) + { + MPlist *p = mplist (); + + mplist_push (ic_info->vars, Mplist, p); + M17N_OBJECT_UNREF (p); + mplist_add (p, Msymbol, name); + mplist_add (p, MPLIST_KEY (pl), MPLIST_VAL (pl)); + } + } + /* Remember the original values. */ + ic_info->vars_saved = mplist_copy (ic_info->vars); + + /* If this input method uses external modules, initialize them. */ + if (im_info->externals) + { + MPlist *func_args = mplist (), *plist; + + mplist_add (func_args, Mt, ic); + MPLIST_DO (plist, im_info->externals) + { + MIMExternalModule *external = MPLIST_VAL (plist); + MIMExternalFunc func + = (MIMExternalFunc) mplist_get_func (external->func_list, Minit); + + if (func) + (func) (func_args); + } + M17N_OBJECT_UNREF (func_args); + } + + ic_info->preedit_saved = mtext (); + + if (fallback_input_methods) + { + /* Record MInputContext of each fallback input method in + ic_info->fallbacks in the preference order. Note that the + input methods in fallback_input_methods are in reverse + preference order. */ + MPlist *fallbacks = fallback_input_methods; + + /* To prevent this part being called recursively via + create_ic_for_im below. */ + fallback_input_methods = NULL; + ic_info->fallbacks = mplist (); + MPLIST_DO (plist, fallbacks) + { + MInputContext *fallback_ic + = create_ic_for_im (MPLIST_PLIST (plist), ic->im); + if (fallback_ic) + mplist_push (ic_info->fallbacks, Mt, fallback_ic); + } + fallback_input_methods = fallbacks; + } + + /* Remember the tick of this input method to know when to + re-initialize ic_info. */ + ic_info->tick = im_info->tick; +} + +/* Finalize IC->ic_info. */ + +static void +fini_ic_info (MInputContext *ic) +{ + MInputMethodInfo *im_info; + MInputContextInfo *ic_info; + MPlist *plist; + + if (((MInputContextInfo *) ic->info)->stack) + pop_im (ic); + im_info = ic->im->info; + ic_info = ic->info; + if (ic_info->fallbacks) + { + MPLIST_DO (plist, ic_info->fallbacks) + { + MInputContext *ic = MPLIST_VAL (plist); + MInputMethod *im = ic->im; + + minput_destroy_ic (ic); + minput_close_im (im); + } + M17N_OBJECT_UNREF (ic_info->fallbacks); + } + if (im_info->externals) + { + MPlist *func_args = mplist (), *plist; + + mplist_add (func_args, Mt, ic); + MPLIST_DO (plist, im_info->externals) + { + MIMExternalModule *external = MPLIST_VAL (plist); + MIMExternalFunc func + = (MIMExternalFunc) mplist_get_func (external->func_list, Mfini); + + if (func) + (func) (func_args); + } + M17N_OBJECT_UNREF (func_args); + } + + MLIST_FREE1 (ic_info, keys); + M17N_OBJECT_UNREF (ic_info->preedit_saved); + M17N_OBJECT_UNREF (ic_info->markers); + M17N_OBJECT_UNREF (ic_info->vars); + M17N_OBJECT_UNREF (ic_info->vars_saved); + M17N_OBJECT_UNREF (ic_info->preceding_text); + M17N_OBJECT_UNREF (ic_info->following_text); + M17N_OBJECT_UNREF (ic_info->pushing_or_switching); + + /* Note that we can clear ic_info->fallbacks and ic_info->stack too + because they should be saved and restored by the caller if + necessary. */ + memset (ic_info, 0, sizeof (MInputContextInfo)); +} + +static void +re_init_ic (MInputContext *ic, int reload) +{ + MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info; + MInputContextInfo *ic_info = (MInputContextInfo *) ic->info; + int status_changed, preedit_changed, cursor_pos_changed, candidates_changed; + /* Remember these now. They are cleared by fini_ic_info (). */ + MIMInputStack *stack = ic_info->stack; + + status_changed = ic_info->state != (MIMState *) MPLIST_VAL (im_info->states); + preedit_changed = mtext_nchars (ic->preedit) > 0; + cursor_pos_changed = ic->cursor_pos > 0; + candidates_changed = 0; + if (ic->candidate_list) + { + candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED; + M17N_OBJECT_UNREF (ic->candidate_list); + ic->candidate_list = NULL; + } + if (ic->candidate_show) + { + candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED; + ic->candidate_show = 0; + } + if (ic->candidate_index > 0) + { + candidates_changed |= MINPUT_CANDIDATES_INDEX_CHANGED; + ic->candidate_index = 0; + ic->candidate_from = ic->candidate_to = 0; + } + if (mtext_nchars (ic->produced) > 0) + mtext_reset (ic->produced); + if (mtext_nchars (ic->preedit) > 0) + mtext_reset (ic->preedit); + ic->cursor_pos = 0; + M17N_OBJECT_UNREF (ic->plist); + ic->plist = mplist (); + + fini_ic_info (ic); + if (reload) + reload_im_info (im_info); + if (! im_info->states) + { + struct MIMState *state; + + M17N_OBJECT (state, free_state, MERROR_IM); + state->name = msymbol ("init"); + state->title = mtext__from_data ("ERROR!", 6, MTEXT_FORMAT_US_ASCII, 0); + MSTRUCT_CALLOC (state->map, MERROR_IM); + im_info->states = mplist (); + mplist_add (im_info->states, state->name, state); + } + init_ic_info (ic); + /* Restore them now. */ + ic_info->stack = stack; + shift_state (ic, Mnil); + + ic->status_changed = status_changed; + ic->preedit_changed = preedit_changed; + ic->cursor_pos_changed = cursor_pos_changed; + ic->candidates_changed = candidates_changed; +} + +static void +reset_ic (MInputContext *ic, MSymbol ignore) +{ + MInputMethodInfo *im_info = ic->im->info; + MDEBUG_PRINT2 ("\n [IM:%s-%s] reset\n", + MSYMBOL_NAME (im_info->language), + MSYMBOL_NAME (im_info->name)); + re_init_ic (ic, 0); +} + +static int +open_im (MInputMethod *im) +{ + MInputMethodInfo *im_info = get_im_info (im->language, im->name, Mnil, Mnil); + + if (! im_info || ! im_info->states || MPLIST_LENGTH (im_info->states) == 0) + MERROR (MERROR_IM, -1); + im->info = im_info; + + return 0; +} + +static void +close_im (MInputMethod *im) +{ + im->info = NULL; +} + +static int +create_ic (MInputContext *ic) +{ + MInputContextInfo *ic_info; + + MSTRUCT_CALLOC (ic_info, MERROR_IM); + ic->info = ic_info; + init_ic_info (ic); + shift_state (ic, Mnil); + return 0; +} + +static void +destroy_ic (MInputContext *ic) +{ + fini_ic_info (ic); + free (ic->info); +} + + +/* Return 1 if KEY is for invoking COMMAND. Otherwise, return 0. */ + +static int +check_command_key (MInputContext *ic, MSymbol key, MSymbol command) +{ + MInputMethodInfo *im_info = ic->im->info; + MPlist *plist = resolve_command (im_info->configured_cmds, command); + + if (! plist) + { + plist = resolve_command (global_info->configured_cmds, command); + if (! plist) + return 0; + } + MPLIST_DO (plist, plist) + { + MSymbol this_key, alias; + + if (MPLIST_MTEXT_P (plist)) + { + MText *mt = MPLIST_MTEXT (plist); + int c = mtext_ref_char (mt, 0); + + if (c >= 256) + continue; + this_key = one_char_symbol[c]; + } + else + { + MPlist *pl = MPLIST_PLIST (plist); + + this_key = MPLIST_SYMBOL (pl); + } + alias = this_key; + while (alias != key + && (alias = msymbol_get (alias, M_key_alias)) + && alias != this_key); + if (alias == key) + break; + } + return ! MPLIST_TAIL_P (plist); +} + +static int +check_reload (MInputContext *ic, MSymbol key) +{ + MInputMethodInfo *im_info = ic->im->info; + if (! check_command_key (ic, key, Mat_reload)) + return 0; + MDEBUG_PRINT2 ("\n [IM:%s-%s] reload", + MSYMBOL_NAME (im_info->language), + MSYMBOL_NAME (im_info->name)); + re_init_ic (ic, 1); + return 1; +} + +static MInputContext * +check_fallback (MInputContext *ic, MSymbol key) +{ + MInputContextInfo *ic_info = ic->info; + MPlist *plist; + + MPLIST_DO (plist, ic_info->fallbacks) + { + MSymbol alias = key; + MInputContext *this_ic = (MInputContext *) MPLIST_VAL (plist); + MInputMethodInfo *this_im_info = (MInputMethodInfo * )this_ic->im->info; + MIMMap *map = ((MIMState *) MPLIST_VAL (this_im_info->states))->map; + MIMMap *submap; + + if (! map->submaps) + continue; + submap = mplist_get (map->submaps, key); + while (! submap + && (alias = msymbol_get (alias, M_key_alias)) + && alias != key) + submap = mplist_get (map->submaps, alias); + if (submap) + return this_ic; + } + return NULL; +} + + +/** Handle the input key KEY in the current state and map of IC->info. + If KEY is handled but no text is produced, return 0, otherwise + return 1. + + Ignore ARG. */ + +static int +filter (MInputContext *ic, MSymbol key, void *arg) +{ + MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info; + MInputContextInfo *ic_info = (MInputContextInfo *) ic->info; + int count = 0; + /* The result of handling keys. + -1: Not handled, or an error occured + 0: Handled normally without changing IM + 1: IM switch + 2: IM pushed + 3: IM poped */ + int result; + + if (check_reload (ic, key)) + return 0; + + if (! ic_info->state) + { + ic_info->key_unhandled = 1; + return 0; + } + mtext_reset (ic->produced); + ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0; + MLIST_APPEND1 (ic_info, keys, key, MERROR_IM); + repeat: + M17N_OBJECT_UNREF (ic_info->preceding_text); + M17N_OBJECT_UNREF (ic_info->following_text); + ic_info->preceding_text = ic_info->following_text = NULL; + ic_info->key_unhandled = 0; + + do { + MPlist *candidate_list = ic->candidate_list; + int candidate_index = ic->candidate_index; + int candidate_show = ic->candidate_show; + MTextProperty *prop; + + result = handle_key (ic); + if (ic->candidate_list) + { + M17N_OBJECT_UNREF (ic->candidate_list); + ic->candidate_list = NULL; + } + if (ic->cursor_pos > 0 + && (prop = mtext_get_property (ic->preedit, ic->cursor_pos - 1, + Mcandidate_list))) + { + ic->candidate_list = mtext_property_value (prop); + M17N_OBJECT_REF (ic->candidate_list); + ic->candidate_index + = (int) mtext_get_prop (ic->preedit, ic->cursor_pos - 1, + Mcandidate_index); + ic->candidate_from = mtext_property_start (prop); + ic->candidate_to = mtext_property_end (prop); + } + if (candidate_list != ic->candidate_list) + ic->candidates_changed |= MINPUT_CANDIDATES_LIST_CHANGED; + if (candidate_index != ic->candidate_index) + ic->candidates_changed |= MINPUT_CANDIDATES_INDEX_CHANGED; + if (candidate_show != ic->candidate_show) + ic->candidates_changed |= MINPUT_CANDIDATES_SHOW_CHANGED; + + if (count++ == 100) + { + /* Insane number of iteration, perhaps a bug. */ + mdebug_hook (); + reset_ic (ic, Mnil); + ic_info->key_unhandled = 1; + break; + } + /* Break the loop if all keys were handled. */ + } while (result == 0 && ic_info->key_head < ic_info->used); + + /* If the current map is the root of the initial state, we should + produce any preedit text in ic->produced, and if the current + input method is a pushed one, pop it. */ + if (ic_info->map == ((MIMState *) MPLIST_VAL (im_info->states))->map) + { + preedit_commit (ic, 1); + if (ic_info->stack) + result = 3; + } + + if (mtext_nchars (ic->produced) > 0) + { + if (MDEBUG_FLAG ()) + { + int i; + + MDEBUG_PRINT3 ("\n [IM:%s-%s] [%s] (produced", + MSYMBOL_NAME (im_info->language), + MSYMBOL_NAME (im_info->name), + MSYMBOL_NAME (ic_info->state->name)); + for (i = 0; i < mtext_nchars (ic->produced); i++) + MDEBUG_PRINT1 (" U+%04X", mtext_ref_char (ic->produced, i)); + MDEBUG_PRINT (")"); + } + + mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced), + Mlanguage, ic->im->language); + } + + if (ic_info->commit_key_head > 0) + { + memmove (ic_info->keys, ic_info->keys + ic_info->commit_key_head, + sizeof (MSymbol *) * (ic_info->used - ic_info->commit_key_head)); + ic_info->used -= ic_info->commit_key_head; + ic_info->key_head -= ic_info->commit_key_head; + ic_info->state_key_head -= ic_info->commit_key_head; + ic_info->commit_key_head = 0; + } + + if (result != 0) + { + MInputContext *pushing = NULL; + + if (ic_info->key_head > 0) + { + memmove (ic_info->keys, ic_info->keys + ic_info->key_head, + sizeof (MSymbol *) * (ic_info->used - ic_info->key_head)); + ic_info->used -= ic_info->key_head; + ic_info->key_head = ic_info->state_key_head + = ic_info->commit_key_head = 0; + } + + if (result < 0) + { + /* KEY was not handled. If the current input method was not + the pushed one, check if it is a key for one of fallback + input methods. */ + if (! ic_info->stack) + { + pushing = check_fallback (ic, ic_info->keys[ic_info->key_head]); + if (pushing) + result = 2; + } + } + if (result < 0) + { + ic_info->used = 0; + ic_info->key_head = ic_info->state_key_head + = ic_info->commit_key_head = 0; + ic_info->key_unhandled = 1; + } + else if (result == 3) /* pop */ + { + pop_im (ic); + ic_info = ic->info; + im_info = ic->im->info; + if (ic_info->key_head < ic_info->used) + goto repeat; + } + else if (result == 2) /* push */ + { + ic_info = push_im (ic, pushing); + if (ic_info) + { + im_info = ic->im->info; + goto repeat; + } + } + else /* (result == 1) switch */ + { + } + } + + return (! ic_info->key_unhandled && mtext_nchars (ic->produced) == 0); +} + + +/** Return 1 if the last event or key was not handled, otherwise + return 0. + + There is no need of looking up because ic->produced should already + contain the produced text (if any). + + Ignore KEY. */ + +static int +lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt) +{ + mtext_cat (mt, ic->produced); + mtext_reset (ic->produced); + return (((MInputContextInfo *) ic->info)->key_unhandled ? -1 : 0); +} + + +/* Input method command handler. */ + +/* List of all (global and local) commands. + (LANG:(IM-NAME:(COMMAND ...) ...) ...) ... + COMMAND is CMD-NAME:(mtext:DESCRIPTION plist:KEYSEQ ...)) + Global commands are stored as (t (t COMMAND ...)) */ + + +/* Input method variable handler. */ + + +/* Support functions for mdebug_dump_im. */ + +static void +dump_im_map (MPlist *map_list, int indent) +{ + char *prefix; + MSymbol key = MPLIST_KEY (map_list); + MIMMap *map = (MIMMap *) MPLIST_VAL (map_list); + + prefix = (char *) alloca (indent + 1); + memset (prefix, 32, indent); + prefix[indent] = '\0'; + + fprintf (mdebug__output, "(\"%s\" ", msymbol_name (key)); + if (map->map_actions) + mdebug_dump_plist (map->map_actions, indent + 2); + if (map->submaps) + { + MPLIST_DO (map_list, map->submaps) + { + fprintf (mdebug__output, "\n%s ", prefix); + dump_im_map (map_list, indent + 2); + } + } + if (map->branch_actions) + { + fprintf (mdebug__output, "\n%s (branch\n%s ", prefix, prefix); + mdebug_dump_plist (map->branch_actions, indent + 4); + fprintf (mdebug__output, ")"); + } + fprintf (mdebug__output, ")"); +} + + +static void +dump_im_state (MIMState *state, int indent) +{ + char *prefix; + MPlist *map_list; + + prefix = (char *) alloca (indent + 1); + memset (prefix, 32, indent); + prefix[indent] = '\0'; + + fprintf (mdebug__output, "(%s", msymbol_name (state->name)); + if (state->map->submaps) + { + MPLIST_DO (map_list, state->map->submaps) + { + fprintf (mdebug__output, "\n%s ", prefix); + dump_im_map (map_list, indent + 2); + } + } + fprintf (mdebug__output, ")"); +} + + + +int +minput__init () +{ + Minput_driver = msymbol ("input-driver"); + + Minput_preedit_start = msymbol ("input-preedit-start"); + Minput_preedit_done = msymbol ("input-preedit-done"); + Minput_preedit_draw = msymbol ("input-preedit-draw"); + Minput_status_start = msymbol ("input-status-start"); + Minput_status_done = msymbol ("input-status-done"); + Minput_status_draw = msymbol ("input-status-draw"); + Minput_candidates_start = msymbol ("input-candidates-start"); + Minput_candidates_done = msymbol ("input-candidates-done"); + Minput_candidates_draw = msymbol ("input-candidates-draw"); + Minput_set_spot = msymbol ("input-set-spot"); + Minput_focus_move = msymbol ("input-focus-move"); + Minput_focus_in = msymbol ("input-focus-in"); + Minput_focus_out = msymbol ("input-focus-out"); + Minput_toggle = msymbol ("input-toggle"); + Minput_reset = msymbol ("input-reset"); + Minput_get_surrounding_text = msymbol ("input-get-surrounding-text"); + Minput_delete_surrounding_text = msymbol ("input-delete-surrounding-text"); + Mcustomized = msymbol ("customized"); + Mconfigured = msymbol ("configured"); + Minherited = msymbol ("inherited"); + + minput_default_driver.open_im = open_im; + minput_default_driver.close_im = close_im; + minput_default_driver.create_ic = create_ic; + minput_default_driver.destroy_ic = destroy_ic; + minput_default_driver.filter = filter; + minput_default_driver.lookup = lookup; + minput_default_driver.callback_list = mplist (); + mplist_put_func (minput_default_driver.callback_list, Minput_reset, + M17N_FUNC (reset_ic)); + minput_driver = &minput_default_driver; + + fully_initialized = 0; + return 0; +} + +void +minput__fini () +{ + if (fully_initialized) + { + MDEBUG_PRINT ("freeing im_info_list\n"); + free_im_list (im_info_list); + MDEBUG_PRINT ("freeing im_custom_list\n"); + if (im_custom_list) + free_im_list (im_custom_list); + MDEBUG_PRINT ("freeing im_config_list\n"); + if (im_config_list) + free_im_list (im_config_list); + M17N_OBJECT_UNREF (load_im_info_keys); + M17N_OBJECT_UNREF (fallback_input_methods); + } + + M17N_OBJECT_UNREF (minput_default_driver.callback_list); + M17N_OBJECT_UNREF (minput_driver->callback_list); +} + +MSymbol +minput__char_to_key (int c) +{ + if (c < 0 || c >= 0x100) + return Mnil; + + return one_char_symbol[c]; +} + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/* External API */ + +/*** @addtogroup m17nInputMethod */ +/*** @{ */ +/*=*/ + +/***en + @brief Symbol whose name is "input-method". + */ +/***ja + @brief "input-method" ��̾���Ȥ��ƻ��ĥ���ܥ�. + */ +MSymbol Minput_method; + +/***en + @name Variables: Predefined symbols for callback commands. */ +/***ja + @name �ѿ��� ������Хå����ޥ��������Ѥߥ���ܥ�. */ +/*** @{ */ +/***en + These are the predefined symbols that are used as the @c COMMAND + argument of callback functions of an input method driver (see + #MInputDriver::callback_list). + + Most of them do not require extra argument nor return any value; + exceptions are these: + + @b Minput_get_surrounding_text: When a callback function assigned for + this command is called, the first element of #MInputContext::plist + has key #Minteger and the value specifies which portion of the + surrounding text should be retrieved. If the value is positive, + it specifies the number of characters following the current cursor + position. If the value is negative, the absolute value specifies + the number of characters preceding the current cursor position. + If the value is zero, it means that the caller just wants to know + if the surrounding text is currently supported or not. + + If the surrounding text is currently supported, the callback + function must set the key of this element to #Mtext and the value + to the retrieved M-text. The length of the M-text may be shorter + than the requested number of characters, if the available text is + not that long. The length can be zero in the worst case. Or, the + length may be longer if an application thinks it is more efficient + to return that length. + + If the surrounding text is not currently supported, the callback + function should return without changing the first element of + #MInputContext::plist. + + @b Minput_delete_surrounding_text: When a callback function assigned + for this command is called, the first element of + #MInputContext::plist has key #Minteger and the value specifies + which portion of the surrounding text should be deleted in the + same way as the case of Minput_get_surrounding_text. The callback + function must delete the specified text. It should not alter + #MInputContext::plist. */ +/***ja + ���ϥ᥽�åɥɥ饤�ФΥ�����Хå��ؿ��ˤ����� @c COMMAND + �����Ȥ����Ѥ���������Ѥߥ���ܥ� (#MInputDriver::callback_list ����)�� + + �ۤȤ�ɤ��ɲäΰ�����ɬ�פȤ��ʤ����ͤ��֤��ʤ������ʲ����㳰�Ǥ��롣 + + Minput_get_surrounding_text: ���Υ��ޥ�ɤ˳�����Ƥ�줿������Х� + ���ؿ����ƤФ줿�ݤˤϡ� #MInputContext::plist ��������Ǥϥ����Ȥ� + ��#Minteger ��Ȥꡢ�����ͤϥ��饦��ǥ��󥰥ƥ����ȤΤ����ɤ���ʬ + ���ä���뤫����ꤹ�롣�ͤ����Ǥ���С����ߤΥ���������֤�³�� + �ͤθĿ�ʬ��ʸ�����롣��Ǥ���С�����������֤���Ԥ����ͤ����� + ��ʬ��ʸ�����롣���ߥ��饦��ɥƥ����Ȥ����ݡ��Ȥ���Ƥ��뤫�ɤ� + �����Τꤿ�������Ǥ���С������ͤϥ����Ǥ��ɤ��� + + ���饦��ǥ��󥰥ƥ����Ȥ����ݡ��Ȥ���Ƥ���С�������Хå��ؿ��� + �������ǤΥ����� #Mtext �ˡ��ͤ�������M-text �����ꤷ�ʤ��ƤϤ� + ��ʤ����⤷�ƥ����Ȥ�Ĺ������ʬ�Ǥʤ���С����� M-text ��Ĺ������ + �ᤵ��Ƥ���ʸ�������û�����ɤ����ǰ��ξ�� 0 �Ǥ�褤�������ץꥱ�� + �����¦��ɬ�פǸ�ΨŪ���Ȼפ���Ĺ���Ƥ��ɤ��� + + ���饦��ǥ��󥰥ƥ����Ȥ����ݡ��Ȥ���Ƥ��ʤ���С�������Хå��� + ���� #MInputContext::plist ��������Ǥ��ѹ����ƤϤʤ�ʤ��� + + Minput_delete_surrounding_text: ���Υ��ޥ�ɤ˳�����Ƥ�줿������ + �Хå��ؿ����ƤФ줿�ݤˤϡ�#MInputContext::plist ��������Ǥϡ����� + �Ȥ���#Minteger ��Ȥꡢ�ͤϺ������٤����饦��ǥ��󥰥ƥ����Ȥ� + Minput_get_surrounding_text ��Ʊ�ͤΤ�����ǻ��ꤹ�롣������Хå� + �ؿ��ϻ��ꤵ�줿�ƥ����Ȥ������ʤ���Фʤ�ʤ����ޤ� + #MInputContext::plist ���Ѥ��ƤϤʤ�ʤ��� */ +MSymbol Minput_preedit_start; +MSymbol Minput_preedit_done; +MSymbol Minput_preedit_draw; +MSymbol Minput_status_start; +MSymbol Minput_status_done; +MSymbol Minput_status_draw; +MSymbol Minput_candidates_start; +MSymbol Minput_candidates_done; +MSymbol Minput_candidates_draw; +MSymbol Minput_set_spot; +MSymbol Minput_toggle; +MSymbol Minput_reset; +MSymbol Minput_get_surrounding_text; +MSymbol Minput_delete_surrounding_text; +/*** @} */ + +/*=*/ + +/***en + @name Variables: Predefined symbols for special input events. + + These are the predefined symbols that are used as the @c KEY + argument of minput_filter (). */ +/***ja + @name �ѿ�: ���̤����ϥ��٥��������Ѥߥ���ܥ�. + + minput_filter () �� @c KEY �����Ȥ����Ѥ���������Ѥߥ���ܥ롣 */ + +/*** @{ */ +/*=*/ + +MSymbol Minput_focus_out; +MSymbol Minput_focus_in; +MSymbol Minput_focus_move; + +/*** @} */ + +/*=*/ +/***en + @name Variables: Predefined symbols used in input method information. */ +/***ja + @name �ѿ�: ���ϥ᥽�åɾ���������Ѥߥ���ܥ�. */ +/*** @{ */ +/*=*/ +/***en + These are the predefined symbols describing status of input method + command and variable, and are used in a return value of + minput_get_command () and minput_get_variable (). */ +/***ja + ���ϥ᥽�åɤΥ��ޥ�ɤ��ѿ��ξ��֤�ɽ����minput_get_command () �� + minput_get_variable () ������ͤȤ����Ѥ���������Ѥߥ���ܥ롣 */ +MSymbol Minherited; +MSymbol Mcustomized; +MSymbol Mconfigured; +/*** @} */ + +/*=*/ + +/***en + @brief The default driver for internal input methods. + + The variable #minput_default_driver is the default driver for + internal input methods. + + The member MInputDriver::open_im () searches the m17n database for + an input method that matches the tag \< #Minput_method, $LANGUAGE, + $NAME\> and loads it. + + The member MInputDriver::callback_list () is @c NULL. Thus, it is + programmers responsibility to set it to a plist of proper callback + functions. Otherwise, no feedback information (e.g. preedit text) + can be shown to users. + + The macro M17N_INIT () sets the variable #minput_driver to the + pointer to this driver so that all internal input methods use it. + + Therefore, unless @c minput_driver is set differently, the driver + dependent arguments $ARG of the functions whose name begins with + "minput_" are all ignored. */ +/***ja + @brief �������ϥ᥽�å��ѥǥե���ȥɥ饤��. + + �ѿ� #minput_default_driver ���������ϥ᥽�å��ѤΥǥե���ȤΥɥ饤�Ф�ɽ���� + + ���� MInputDriver::open_im () �� m17n �ǡ����١����椫�饿�� + \< #Minput_method, $LANGUAGE, $NAME\> + �˹��פ������ϥ᥽�åɤ�õ�������������ɤ��롣 + + ���� MInputDriver::callback_list () �� @c NULL �Ǥ��ꡢ + �������äơ��ץ������¦����Ǥ����ä� Ŭ�ڤʥ�����Хå��ؿ��� plist + �����ꤷ�ʤ��ƤϤʤ�ʤ�������ʤ��ȡ�preedit + �ƥ����ȤʤɤΥե����ɥХå����󤬥桼����ɽ������ʤ��� + + �ޥ��� M17N_INIT () ���ѿ� #minput_driver + �򤳤Υɥ饤�ФؤΥݥ��󥿤����ꤷ�����Ƥ��������ϥ᥽�åɤ����Υɥ饤�Ф�Ȥ��褦�ˤ��롣 + + �������äơ�@c minput_driver ���ǥե�����ͤΤޤޤǤ���С�minput_ + �ǻϤޤ�ؿ��Υɥ饤�Ф˰�¸������� $ARG �Ϥ��٤�̵�뤵��롣 */ + +MInputDriver minput_default_driver; +/*=*/ + +/***en + @brief The driver for internal input methods. + + The variable #minput_driver is a pointer to the input method + driver that is used by internal input methods. The macro + M17N_INIT () initializes it to a pointer to #minput_default_driver + if .h> is included. */ +/***ja + @brief �������ϥ᥽�å��ѥɥ饤��. + + �ѿ� #minput_driver ���������ϥ᥽�åɤˤ�äƻ��Ѥ���Ƥ������ϥ� + ���åɥɥ饤�ФؤΥݥ��󥿤Ǥ��롣�ޥ��� M17N_INIT () �Ϥ��Υݥ��� + ����#minput_default_driver (.h> �� include ����Ƥ��� + ��) �˽�������롣 */ + +MInputDriver *minput_driver; + +/*=*/ +/*** + The variable #Minput_driver is a symbol for a foreign input method. + See @ref foreign-input-method "foreign input method" for the detail. */ +MSymbol Minput_driver; + +/*=*/ + +/***en + @name Functions +*/ +/***ja + @name �ؿ� +*/ +/*** @{ */ + +/*=*/ + +/***en + @brief Open an input method. + + The minput_open_im () function opens an input method whose + language and name match $LANGUAGE and $NAME, and returns a pointer + to the input method object newly allocated. + + This function at first decides a driver for the input method as + described below. + + If $LANGUAGE is not #Mnil, the driver pointed by the variable + #minput_driver is used. + + If $LANGUAGE is #Mnil and $NAME has the property #Minput_driver, the + driver pointed to by the property value is used to open the input + method. If $NAME has no such a property, @c NULL is returned. + + Then, the member MInputDriver::open_im () of the driver is + called. + + $ARG is set in the member @c arg of the structure MInputMethod so + that the driver can refer to it. */ +/***ja + @brief ���ϥ᥽�åɤ򥪡��ץ󤹤�. + + �ؿ� minput_open_im () �ϸ��� $LANGUAGE ��̾�� $NAME + �˹��פ������ϥ᥽�åɤ򥪡��ץ󤷡������˳�����Ƥ�줿���ϥ᥽�åɥ��֥������ȤؤΥݥ��󥿤��֤��� + + ���δؿ��ϡ��ޤ����ϥ᥽�å��ѤΥɥ饤�Ф�ʲ��Τ褦�ˤ��Ʒ��ꤹ�롣 + + $LANGUAGE �� #Mnil �Ǥʤ���С��ѿ� #minput_driver + �ǻؤ���Ƥ���ɥ饤�Ф��Ѥ��롣 + + $LANGUAGE �� #Mnil �Ǥ��ꡢ$NAME �� #Minput_driver + �ץ��ѥƥ�����ľ��ˤϡ����Υץ��ѥƥ����ͤǻؤ���Ƥ������ϥɥ饤�Ф��Ѥ������ϥ᥽�åɤ򥪡��ץ󤹤롣 + $NAME �ˤ��Τ褦�ʥץ��ѥƥ���̵���ä����� @c NULL ���֤��� + + �����ǡ��ɥ饤�ФΥ��� MInputDriver::open_im () ���ƤФ�롣 + + $ARG �Ϲ�¤�� MInputMethod �Υ��� @c arg �����ꤵ�졢�ɥ饤�Ф��黲�ȤǤ��롣 + + @latexonly \IPAlabel{minput_open} @endlatexonly + +*/ + +MInputMethod * +minput_open_im (MSymbol language, MSymbol name, void *arg) +{ + MInputMethod *im; + MInputDriver *driver; + + MINPUT__INIT (); + + MDEBUG_PRINT2 (" [IM:%s-%s] opening ... ", + MSYMBOL_NAME (language), MSYMBOL_NAME (name)); + if (language) + { + if (name == Mnil) + MERROR (MERROR_IM, NULL); + driver = minput_driver; + } + else + { + driver = (MInputDriver *) msymbol_get (name, Minput_driver); + if (! driver) + MERROR (MERROR_IM, NULL); + } + + MSTRUCT_CALLOC (im, MERROR_IM); + im->language = language; + im->name = name; + im->arg = arg; + im->driver = *driver; + if ((*im->driver.open_im) (im) < 0) + { + MDEBUG_PRINT (" failed\n"); + free (im); + return NULL; + } + MDEBUG_PRINT (" ok\n"); + return im; +} + +/*=*/ + +/***en + @brief Close an input method. + + The minput_close_im () function closes the input method $IM, which + must have been created by minput_open_im (). */ + +/***ja + @brief ���ϥ᥽�åɤ򥯥���������. + + �ؿ� minput_close_im () �ϡ����ϥ᥽�å� $IM �򥯥��������롣 + �������ϥ᥽�å� $IM �� minput_open_im () �ˤ�äƺ��줿��ΤǤʤ���Фʤ�ʤ��� */ + +void +minput_close_im (MInputMethod *im) +{ + MDEBUG_PRINT2 (" [IM:%s-%s] closing ... ", + MSYMBOL_NAME (im->language), MSYMBOL_NAME (im->name)); + (*im->driver.close_im) (im); + free (im); + MDEBUG_PRINT (" done\n"); +} + +/*=*/ + +/***en + @brief Create an input context. + + The minput_create_ic () function creates an input context object + associated with input method $IM, and calls callback functions + corresponding to @b Minput_preedit_start, @b Minput_status_start, and + @b Minput_status_draw in this order. + + @return + If an input context is successfully created, minput_create_ic () + returns a pointer to it. Otherwise it returns @c NULL. */ + +/***ja + @brief ���ϥ���ƥ����Ȥ���������. + + �ؿ� minput_create_ic () �����ϥ᥽�å� $IM + ���б��������ϥ���ƥ����ȥ��֥������Ȥ��������� + @b Minput_preedit_start, @b Minput_status_start, @b Minput_status_draw + ���б����륳����Хå��ؿ��򤳤ν�˸Ƥ֡� + + @return + ���ϥ���ƥ����Ȥ��������줿��硢minput_create_ic () + �Ϥ������ϥ���ƥ����ȤؤΥݥ��󥿤��֤������Ԥ������� @c NULL ���֤��� + */ + +MInputContext * +minput_create_ic (MInputMethod *im, void *arg) +{ + MInputContext *ic; + + MDEBUG_PRINT2 (" [IM:%s-%s] creating context ... ", + MSYMBOL_NAME (im->language), MSYMBOL_NAME (im->name)); + MSTRUCT_CALLOC (ic, MERROR_IM); + ic->im = im; + ic->arg = arg; + ic->preedit = mtext (); + ic->candidate_list = NULL; + ic->produced = mtext (); + ic->spot.x = ic->spot.y = 0; + ic->active = 1; + ic->plist = mplist (); + if ((*im->driver.create_ic) (ic) < 0) + { + MDEBUG_PRINT (" failed\n"); + M17N_OBJECT_UNREF (ic->preedit); + M17N_OBJECT_UNREF (ic->produced); + M17N_OBJECT_UNREF (ic->plist); + free (ic); + return NULL; + }; + + if (im->driver.callback_list) + { + minput_callback (ic, Minput_preedit_start); + minput_callback (ic, Minput_status_start); + minput_callback (ic, Minput_status_draw); + } + + MDEBUG_PRINT (" ok\n"); + return ic; +} + +/*=*/ + +/***en + @brief Destroy an input context. + + The minput_destroy_ic () function destroys the input context $IC, + which must have been created by minput_create_ic (). It calls + callback functions corresponding to @b Minput_preedit_done, + @b Minput_status_done, and @b Minput_candidates_done in this order. */ + +/***ja + @brief ���ϥ���ƥ����Ȥ��˲�����. + + �ؿ� minput_destroy_ic () �ϡ����ϥ���ƥ����� $IC ���˲����롣 + �������ϥ���ƥ����Ȥ� minput_create_ic () + �ˤ�äƺ��줿��ΤǤʤ���Фʤ�ʤ������δؿ��� + @b Minput_preedit_done, @b Minput_status_done, @b Minput_candidates_done + ���б����륳����Хå��ؿ��򤳤ν�˸Ƥ֡� + */ + +void +minput_destroy_ic (MInputContext *ic) +{ + MDEBUG_PRINT2 (" [IM:%s-%s] destroying context ... ", + MSYMBOL_NAME (ic->im->language), MSYMBOL_NAME (ic->im->name)); + if (ic->im->driver.callback_list) + { + minput_callback (ic, Minput_preedit_done); + minput_callback (ic, Minput_status_done); + minput_callback (ic, Minput_candidates_done); + } + (*ic->im->driver.destroy_ic) (ic); + M17N_OBJECT_UNREF (ic->preedit); + M17N_OBJECT_UNREF (ic->produced); + M17N_OBJECT_UNREF (ic->plist); + MDEBUG_PRINT (" done\n"); + free (ic); +} + +/*=*/ + +/***en + @brief Filter an input key. + + The minput_filter () function filters input key $KEY according to + input context $IC, and calls callback functions corresponding to + @b Minput_preedit_draw, @b Minput_status_draw, and + @b Minput_candidates_draw if the preedit text, the status, and the + current candidate are changed respectively. + + To make the input method commit the current preedit text (if any) + and shift to the initial state, call this function with #Mnil as + $KEY. + + To inform the input method about the focus-out event, call this + function with @b Minput_focus_out as $KEY. + + To inform the input method about the focus-in event, call this + function with @b Minput_focus_in as $KEY. + + To inform the input method about the focus-move event (i.e. input + spot change within the same input context), call this function + with @b Minput_focus_move as $KEY. + + @return + If $KEY is filtered out, this function returns 1. In that case, + the caller should discard the key. Otherwise, it returns 0, and + the caller should handle the key, for instance, by calling the + function minput_lookup () with the same key. */ + +/***ja + @brief ���ϥ�����ե��륿����. + + �ؿ� minput_filter () �����ϥ��� $KEY �����ϥ���ƥ����� $IC + �˱����ƥե��륿����preedit �ƥ����ȡ����ơ��������������Ǥθ��䤬�Ѳ����������ǡ����줾�� + @b Minput_preedit_draw, @b Minput_status_draw, + @b Minput_candidates_draw ���б����륳����Хå��ؿ���Ƥ֡� + + @return + $KEY ���ե��륿�����С����δؿ��� 1 ���֤��� + ���ξ��ƤӽФ�¦�Ϥ��Υ�����ΤƤ�٤��Ǥ��롣 + �����Ǥʤ���� 0 ���֤����ƤӽФ�¦�ϡ����Ȥ���Ʊ�������Ǵؿ� minput_lookup () + ��Ƥ֤ʤɤ��ơ����Υ�����������롣 + + @latexonly \IPAlabel{minput_filter} @endlatexonly +*/ + +int +minput_filter (MInputContext *ic, MSymbol key, void *arg) +{ + int ret; + + if (! ic + || ! ic->active) + return 0; + if (ic->im->driver.callback_list + && mtext_nchars (ic->preedit) > 0) + minput_callback (ic, Minput_preedit_draw); + + ret = (*ic->im->driver.filter) (ic, key, arg); + + if (ic->im->driver.callback_list) + { + if (ic->preedit_changed) + minput_callback (ic, Minput_preedit_draw); + if (ic->status_changed) + minput_callback (ic, Minput_status_draw); + if (ic->candidates_changed) + minput_callback (ic, Minput_candidates_draw); + } + + return ret; +} + +/*=*/ + +/***en + @brief Look up a text produced in the input context. + + The minput_lookup () function looks up a text in the input context + $IC. $KEY must be identical to the one that was used in the previous call of + minput_filter (). + + If a text was produced by the input method, it is concatenated + to M-text $MT. + + This function calls #MInputDriver::lookup . + + @return + If $KEY was correctly handled by the input method, this function + returns 0. Otherwise, it returns -1, even though some text + might be produced in $MT. */ + +/***ja + @brief ���ϥ���ƥ�������Υƥ����Ȥ�õ��. + + �ؿ� minput_lookup () �����ϥ���ƥ����� $IC ��Υƥ����Ȥ�õ���� + $KEY �ϴؿ� minput_filter () �ؤ�ľ���θƤӽФ����Ѥ���줿��Τ�Ʊ���Ǥʤ��ƤϤʤ�ʤ��� + + �ƥ����Ȥ����ϥ᥽�åɤˤ�ä���������Ƥ���С��ƥ����Ȥ� M-text + $MT ��Ϣ�뤵��롣 + + ���δؿ��ϡ�#MInputDriver::lookup ��Ƥ֡� + + @return + $KEY �����ϥ᥽�åɤˤ�ä�Ŭ�ڤ˽����Ǥ���С����δؿ��� 0 ���֤��� + �����Ǥʤ���� -1 ���֤��� + ���ξ��Ǥ� $MT �˲��餫�Υƥ����Ȥ���������Ƥ��뤳�Ȥ����롣 + + @latexonly \IPAlabel{minput_lookup} @endlatexonly */ + +int +minput_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt) +{ + return (ic ? (*ic->im->driver.lookup) (ic, key, arg, mt) : -1); +} +/*=*/ + +/***en + @brief Set the spot of the input context. + + The minput_set_spot () function sets the spot of input context $IC + to coordinate ($X, $Y ) with the height specified by $ASCENT and $DESCENT . + The semantics of these values depends on the input method driver. + + For instance, a driver designed to work in a CUI environment may + use $X and $Y as the column- and row numbers, and may ignore $ASCENT and + $DESCENT . A driver designed to work in a window system may + interpret $X and $Y as the pixel offsets relative to the origin of the + client window, and may interpret $ASCENT and $DESCENT as the ascent- and + descent pixels of the line at ($X . $Y ). + + $FONTSIZE specifies the fontsize of preedit text in 1/10 point. + + $MT and $POS are the M-text and the character position at the spot. + $MT may be @c NULL, in which case, the input method cannot get + information about the text around the spot. */ + +/***ja + @brief ���ϥ���ƥ����ȤΥ��ݥåȤ����ꤹ��. + + �ؿ� minput_set_spot () �ϡ����ϥ���ƥ����� $IC �Υ��ݥåȤ򡢺�ɸ ($X, $Y ) + �ΰ��֤� ���⤵ $ASCENT�� $DESCENT + �����ꤹ�롣 �������ͤΰ�̣�����ϥ᥽�åɥɥ饤�Ф˰�¸���롣 + + ���Ȥ��� CUI �Ķ���ư���ɥ饤�Ф� $X �� $Y + �򤽤줾����ȹԤ��ֹ�Ȥ����Ѥ���$ASCENT �� $DESCENT + ��̵�뤹�뤫�⤷��ʤ��� �ޤ�������ɥ������ƥ��ѤΥɥ饤�Ф� + $X �� $Y �򥯥饤����ȥ�����ɥ��θ�������Υ��ե��åȤ�ԥ�����ñ�̤�ɽ������ΤȤ��ư����� + $ASCENT �� $DESCENT �� ($X . $Y ) + ����Υ�����Ȥȥǥ�����Ȥ�ԥ�����ñ�̤�ɽ������ΤȤ��ư������⤷��ʤ��� + + $FONTSIZE �ˤ� preedit �ƥ����ȤΥե���ȥ������� 1/10 �ݥ����ñ�̤ǻ��ꤹ�롣 + + $MT �� $POS �Ϥ��Υ��ݥåȤ� M-text ��ʸ�����֤Ǥ��롣$MT �� @c + NULL �Ǥ�褯�����ξ��ˤ����ϥ᥽�åɤϥ��ݥåȼ��դΥƥ����Ȥ˴ؤ����������뤳�Ȥ��Ǥ��ʤ��� + */ + +void +minput_set_spot (MInputContext *ic, int x, int y, + int ascent, int descent, int fontsize, + MText *mt, int pos) +{ + ic->spot.x = x; + ic->spot.y = y; + ic->spot.ascent = ascent; + ic->spot.descent = descent; + ic->spot.fontsize = fontsize; + ic->spot.mt = mt; + ic->spot.pos = pos; + if (ic->im->driver.callback_list) + minput_callback (ic, Minput_set_spot); +} +/*=*/ + +/***en + @brief Toggle input method. + + The minput_toggle () function toggles the input method associated + with input context $IC. */ +/***ja + @brief ���ϥ᥽�åɤ����ؤ���. + + �ؿ� minput_toggle () �����ϥ���ƥ����� $IC + ���б��դ���줿���ϥ᥽�åɤ�ȥ��뤹�롣 + */ + +void +minput_toggle (MInputContext *ic) +{ + if (ic->im->driver.callback_list) + minput_callback (ic, Minput_toggle); + ic->active = ! ic->active; +} + +/*=*/ + +/***en + @brief Reset an input context. + + The minput_reset_ic () function resets input context $IC by + calling a callback function corresponding to @b Minput_reset. It + resets the status of $IC to its initial one. As the + current preedit text is deleted without commitment, if necessary, + call minput_filter () with the arg @b key #Mnil to force the input + method to commit the preedit in advance. */ + +/***ja + @brief ���ϥ���ƥ����Ȥ�ꥻ�åȤ���. + + �ؿ� minput_reset_ic () �� @b Minput_reset ���б����륳����Хå��ؿ� + ��Ƥ֤��Ȥˤ�ä����ϥ���ƥ����� $IC ��ꥻ�åȤ��롣�ꥻ�åȤȤϡ� + �ºݤˤ����ϥ᥽�åɤ������֤˰ܤ����ȤǤ��롣����������Υƥ��� + �Ȥϥ��ߥåȤ���뤳�Ȥʤ���������Τǡ����ץꥱ�������ץ����� + ��ϡ�ɬ�פʤ��ͽ�� minput_filter () ����� @b key #Mnil �ǸƤ�� + ����Ū�˥ץꥨ�ǥ��åȥƥ����Ȥ򥳥ߥåȤ����뤳�ȡ� */ + +void +minput_reset_ic (MInputContext *ic) +{ + if (ic->im->driver.callback_list) + minput_callback (ic, Minput_reset); +} + +/*=*/ + +/***en + @brief Get title and icon filename of an input method. + + The minput_get_title_icon () function returns a plist containing a + title and icon filename (if any) of an input method specified by + $LANGUAGE and $NAME. + + The first element of the plist has key #Mtext and the value is an + M-text of the title for identifying the input method. The second + element (if any) has key #Mtext and the value is an M-text of the + icon image (absolute) filename for the same purpose. + + @return + If there exists a specified input method and it defines an title, + a plist is returned. Otherwise, NULL is returned. The caller + must free the plist by m17n_object_unref (). */ +/***ja + @brief ���ϥ᥽�åɤΥ����ȥ�ȥ��������ѥե�����̾������. + + �ؿ� minput_get_title_icon () �ϡ� $LANGUAGE �� $NAME �ǻ��ꤵ��� + ���ϥ᥽�åɤΥ����ȥ�ȡʤ���С˥��������ѥե������ޤ� plist �� + �֤��� + + plist ��������Ǥϡ�#Mtext �򥭡��˻������ͤ����ϥ᥽�åɤ��̤��� + �����ȥ��ɽ�� M-text �Ǥ��롣�������Ǥ�����С������� #Mtext �Ǥ� + �ꡢ�ͤϼ����ѥ�����������ե���������Хѥ���ɽ�� M-text �Ǥ��롣 + + @return + ��������ϥ᥽�åɤ�¸�ߤ��������ȥ뤬�������Ƥ���� + plist ���֤��������Ǥʤ���� NULL ���֤����ƽ�¦�� + �ؿ� m17n_object_unref () ���Ѥ��� plist ��������ʤ��ƤϤʤ�ʤ��� */ + +MPlist * +minput_get_title_icon (MSymbol language, MSymbol name) +{ + MInputMethodInfo *im_info; + MPlist *plist; + char *file = NULL; + MText *mt; + + MINPUT__INIT (); + + im_info = get_im_info (language, name, Mnil, Mtitle); + if (! im_info || !im_info->title) + return NULL; + mt = mtext_get_prop (im_info->title, 0, Mtext); + if (mt) + file = mdatabase__find_file ((char *) MTEXT_DATA (mt)); + else + { + char *buf = alloca (MSYMBOL_NAMELEN (language) + MSYMBOL_NAMELEN (name) + + 12); + + sprintf (buf, "icons/%s-%s.png", (char *) MSYMBOL_NAME (language), + (char *) MSYMBOL_NAME (name)); + file = mdatabase__find_file (buf); + if (! file && language == Mt) + { + sprintf (buf, "icons/%s.png", (char *) MSYMBOL_NAME (name)); + file = mdatabase__find_file (buf); + } + } + + plist = mplist (); + mplist_add (plist, Mtext, im_info->title); + if (file) + { + mt = mtext__from_data (file, strlen (file), MTEXT_FORMAT_UTF_8, 1); + free (file); + mplist_add (plist, Mtext, mt); + M17N_OBJECT_UNREF (mt); + } + return plist; +} + +/*=*/ + +/***en + @brief Get description text of an input method. + + The minput_get_description () function returns an M-text that + describes the input method specified by $LANGUAGE and $NAME. + + @return + If the specified input method has a description text, a pointer to + #MText is returned. The caller has to free it by m17n_object_unref (). + If the input method does not have a description text, @c NULL is + returned. */ +/***ja + @brief ���ϥ᥽�åɤ������ƥ����Ȥ�����. + + �ؿ� minput_get_description () �ϡ�$LANGUAGE �� $NAME �ˤ�äƻ��� + ���줿���ϥ᥽�åɤ��������� M-text ���֤��� + + @return + ���ꤵ�줿���ϥ᥽�åɤ���������ƥ����Ȥ���äƤ���С� + #MText �ؤΥݥ��󥿤��֤����ƤӽФ�¦�ϡ������ m17n_object_unref + () ���Ѥ��Ʋ������ʤ��ƤϤʤ�ʤ������ϥ᥽�åɤ������ƥ����Ȥ�̵�� + ���@c NULL ���֤��� */ + +MText * +minput_get_description (MSymbol language, MSymbol name) +{ + MInputMethodInfo *im_info; + MSymbol extra; + + MINPUT__INIT (); + + if (name != Mnil) + extra = Mnil; + else + extra = language, language = Mt; + + im_info = get_im_info (language, name, extra, Mdescription); + if (! im_info || ! im_info->description) + return NULL; + M17N_OBJECT_REF (im_info->description); + return im_info->description; +} + +/*=*/ + +/***en + @brief Get information about input method command(s). + + The minput_get_command () function returns information about + the command $COMMAND of the input method specified by $LANGUAGE and + $NAME. An input method command is a pseudo key event to which one + or more actual input key sequences are assigned. + + There are two kinds of commands, global and local. A global + command has a global definition, and the description and the key + assignment may be inherited by a local command. Each input method + defines a local command which has a local key assignment. It may + also declare a local command that inherits the definition of a + global command of the same name. + + If $LANGUAGE is #Mt and $NAME is #Mnil, this function returns + information about a global command. Otherwise information about a + local command is returned. + + If $COMMAND is #Mnil, information about all commands is returned. + + The return value is a @e well-formed plist (@ref m17nPlist) of this + format: +@verbatim + ((NAME DESCRIPTION STATUS [KEYSEQ ...]) ...) +@endverbatim + @c NAME is a symbol representing the command name. + + @c DESCRIPTION is an M-text describing the command, or #Mnil if the + command has no description. + + @c STATUS is a symbol representing how the key assignment is decided. + The value is #Mnil (the default key assignment), @b Mcustomized (the + key assignment is customized by per-user customization file), or + @b Mconfigured (the key assignment is set by the call of + minput_config_command ()). For a local command only, it may also + be @b Minherited (the key assignment is inherited from the + corresponding global command). + + @c KEYSEQ is a plist of one or more symbols representing a key + sequence assigned to the command. If there's no KEYSEQ, the + command is currently disabled (i.e. no key sequence can trigger + actions of the command). + + If $COMMAND is not #Mnil, the first element of the returned plist + contains the information about $COMMAND. + + @return + + If the requested information was found, a pointer to a non-empty + plist is returned. As the plist is kept in the library, the + caller must not modify nor free it. + + Otherwise (the specified input method or the specified command + does not exist), @c NULL is returned. */ +/***ja + @brief ���ϥ᥽�åɤΥ��ޥ�ɤ˴ؤ�����������. + + �ؿ� minput_get_command () �ϡ�$LANGUAGE �� $NAME �ǻ��ꤵ������� + �᥽�åɤΥ��ޥ�� $COMMAND �˴ؤ��������֤������ϥ᥽�åɤΥ��� + ��ɤȤϡ������������٥�ȤǤ��ꡢ���İʾ�μºݤ����ϥ����������� + �󥹤�������Ƥ��롣 + + ���ޥ�ɤˤϡ��������Х�ȥ�������Σ����ब���롣�������Х�ʥ��ޥ�� + �ϥ������Х��������졢��������ʥ��ޥ�ɤϤ��������ȥ���������� + ��Ѿ����뤳�Ȥ��Ǥ��롣�����ϥ᥽�åɤϥ�������ʥ�����������ĥ��� + ����ʥ��ޥ�ɤ�������롣�ޤ�Ʊ̾�Υ������Х�ʥ��ޥ�ɤ������� + �������������ʥ��ޥ�ɤ�������뤳�Ȥ�Ǥ��롣 + + $LANGUAGE �� #Mt �� $NAME �� #Mnil �ξ��ϡ����δؿ��ϥ������Х륳 + �ޥ�ɤ˴ؤ��������֤��������Ǥʤ���Х������륳�ޥ�ɤ˴ؤ���� + �Τ��֤��� + + $COMMAND �� #Mnil �ξ��ϡ����٤ƤΥ��ޥ�ɤ˴ؤ��������֤��� + + ����ͤϰʲ��η����� @e well-formed plist (@ref m17nPlist) �Ǥ��롣 + +@verbatim + ((NAME DESCRIPTION STATUS [KEYSEQ ...]) ...) +@endverbatim + @c NAME �ϥ��ޥ��̾�򼨤�����ܥ�Ǥ��롣 + + @c DESCRIPTION �ϥ��ޥ�ɤ��������� M-text �Ǥ��뤫��������̵������ + �� #Mnil �Ǥ��롣 + + @c STATUS �ϥ���������Ƥ��ɤΤ褦�������뤫�򤢤�魯����ܥ� + �Ǥ��ꡢ�����ͤ� #Mnil �ʥǥե���Ȥγ�����ơ�, @b Mcustomized �ʥ桼 + ����Υ������ޥ����ե�����ˤ�äƥ������ޥ������줿������ơ�, + @b Mconfigured ��minput_config_command ()��Ƥ֤��Ȥˤ�ä����ꤵ��� + ������ơˤΤ����줫�Ǥ��롣�������륳�ޥ�ɤξ��ˤϡ� + @b Minherited ���б����륰�����Х륳�ޥ�ɤ���ηѾ��ˤ�������ơ� + �Ǥ�褤�� + + @c KEYSEQ �ϣ��İʾ�Υ���ܥ뤫��ʤ� plist �Ǥ��ꡢ�ƥ���ܥ�ϥ��� + ��ɤ˳�����Ƥ��Ƥ��륭�����������󥹤�ɽ����KEYSEQ ��̵�����ϡ� + ���Υ��ޥ�ɤϸ����ǻ�����ǽ�Ǥ��롣�ʤ��ʤ�����ޥ�ɤ�ư��� + ư�Ǥ��륭�����������󥹤�̵������ + + $COMMAND �� #Mnil �Ǥʤ���С��֤���� plist �κǽ�����Ǥϡ� + $COMMAND �˴ؤ�������ޤࡣ + + @return + + ����줿���󤬸��Ĥ���С����Ǥʤ� plist �ؤΥݥ��󥿤��֤����ꥹ + �Ȥϥ饤�֥�꤬�������Ƥ���Τǡ��ƽ�¦���ѹ���������������ꤹ�� + ���ȤϤǤ��ʤ��� + + �����Ǥʤ���С����ʤ����������ϥ᥽�åɤ䥳�ޥ�ɤ�¸�ߤ��ʤ���� + @c NULL ���֤��� */ + +#if EXAMPLE_CODE +MText * +get_im_command_description (MSymbol language, MSymbol name, MSymbol command) +{ + /* Return a description of the command COMMAND of the input method + specified by LANGUAGE and NAME. */ + MPlist *cmd = minput_get_command (language, name, command); + MPlist *plist; + + if (! cmds) + return NULL; + plist = mplist_value (cmds); /* (NAME DESCRIPTION STATUS KEY-SEQ ...) */ + plist = mplist_next (plist); /* (DESCRIPTION STATUS KEY-SEQ ...) */ + return (mplist_key (plist) == Mtext + ? (MText *) mplist_value (plist) + : NULL); +} +#endif + +MPlist * +minput_get_command (MSymbol language, MSymbol name, MSymbol command) +{ + MInputMethodInfo *im_info; + + MINPUT__INIT (); + + im_info = get_im_info (language, name, Mnil, Mcommand); + if (! im_info + || ! im_info->configured_cmds + || MPLIST_TAIL_P (im_info->configured_cmds)) + return NULL; + if (command == Mnil) + return im_info->configured_cmds; + return mplist__assq (im_info->configured_cmds, command); +} + +/*=*/ + +/***en + @brief Configure the key sequence of an input method command. + + The minput_config_command () function assigns a list of key + sequences $KEYSEQLIST to the command $COMMAND of the input method + specified by $LANGUAGE and $NAME. + + If $KEYSEQLIST is a non-empty plist, it must be a list of key + sequences, and each key sequence must be a plist of symbols. + + If $KEYSEQLIST is an empty plist, any configuration and + customization of the command are cancelled, and default key + sequences become effective. + + If $KEYSEQLIST is NULL, the configuration of the command is + canceled, and the original key sequences (what saved in per-user + customization file, or the default one) become effective. + + In the latter two cases, $COMMAND can be #Mnil to make all the + commands of the input method the target of the operation. + + If $NAME is #Mnil, this function configures the key assignment of a + global command, not that of a specific input method. + + The configuration takes effect for input methods opened or + re-opened later in the current session. In order to make the + configuration take effect for the future session, it must be saved + in a per-user customization file by the function + minput_save_config (). + + @return + If the operation was successful, this function returns 0, + otherwise returns -1. The operation fails in these cases: +
    +
  • $KEYSEQLIST is not in a valid form. +
  • $COMMAND is not available for the input method. +
  • $LANGUAGE and $NAME do not specify an existing input method. +
+ + @seealso + minput_get_commands (), minput_save_config (). +*/ +/***ja + @brief ���ϥ᥽�åɤΥ��ޥ�ɤΥ������������󥹤����ꤹ��. + + �ؿ� minput_config_command () �ϥ������������󥹤Υꥹ�� + $KEYSEQLIST ��$LANGUAGE �� $NAME �ˤ�äƻ��ꤵ������ϥ᥽�åɤ� + ���ޥ�� $COMMAND �˳�����Ƥ롣 + + $KEYSEQLIST �����ꥹ�ȤǤʤ���С��������������󥹤Υꥹ�ȤǤ��ꡢ + �ƥ������������󥹤ϥ���ܥ�� plist �Ǥ��롣 + + $KEYSEQLIST ������ plist �ʤ�С����Υ��ޥ�ɤ�����䥫�����ޥ����� + ���٤ƥ���󥻥뤵�졢�ǥե���ȤΥ������������󥹤�ͭ���ˤʤ롣 + + $KEYSEQLIST �� NULL �Ǥ���С����Υ��ޥ�ɤ�����ϥ���󥻥뤵�졢 + ���Υ������������󥹡ʥ桼����Υ������ޥ����ե��������¸����Ƥ� + ���Ρ����뤤�ϥǥե���ȤΤ�Ρˤ�ͭ���ˤʤ롣 + + ��Τդ��Ĥξ��ˤϡ�$COMMAND �� #Mnil ��Ȥ뤳�Ȥ��Ǥ���������� + �ϥ᥽�åɤ����ƤΥ��ޥ������Υ���󥻥���̣���롣 + + $NAME �� #Mnil �ʤ�С����δؿ��ϸġ������ϥ᥽�åɤǤϤʤ��������� + ��ʥ��ޥ�ɤΥ���������Ƥ����ꤹ�롣 + + ����������ϡ����ԤΥ��å����������ϥ᥽�åɤ������ץ�ʤޤ��� + �ƥ����ץ�ˤ��줿������ͭ���ˤʤ롣����Υ��å������Ǥ�ͭ���ˤ� + �뤿��ˤϡ��ؿ� minput_save_config () ���Ѥ��ƥ桼����Υ������ޥ� + ���ե��������¸���ʤ��ƤϤʤ�ʤ��� + + @return + + ���δؿ��ϡ���������������� 0 �򡢼��Ԥ���� -1 ���֤������ԤȤϰʲ��ξ��Ǥ��롣 +
    +
  • $KEYSEQLIST ��ͭ���ʷ����Ǥʤ��� +
  • $COMMAND ����������ϥ᥽�åɤ����ѤǤ��ʤ��� +
  • $LANGUAGE �� $NAME �ǻ��ꤵ������ϥ᥽�åɤ�¸�ߤ��ʤ��� +
+ + @seealso + minput_get_commands (), minput_save_config (). +*/ + +#if EXAMPLE_CODE +/* Add "C-x u" to the "start" command of Unicode input method. */ +{ + MSymbol start_command = msymbol ("start"); + MSymbol unicode = msymbol ("unicode"); + MPlist *cmd, *plist, *key_seq_list, *key_seq; + + /* At first get the current key-sequence assignment. */ + cmd = minput_get_command (Mt, unicode, start_command); + if (! cmd) + { + /* The input method does not have the command "start". Here + should come some error handling code. */ + } + /* Now CMD == ((start DESCRIPTION STATUS KEY-SEQUENCE ...) ...). + Extract the part (KEY-SEQUENCE ...). */ + plist = mplist_next (mplist_next (mplist_next (mplist_value (cmd)))); + /* Copy it because we should not modify it directly. */ + key_seq_list = mplist_copy (plist); + + key_seq = mplist (); + mplist_add (key_seq, Msymbol, msymbol ("C-x")); + mplist_add (key_seq, Msymbol, msymbol ("u")); + mplist_add (key_seq_list, Mplist, key_seq); + m17n_object_unref (key_seq); + + minput_config_command (Mt, unicode, start_command, key_seq_list); + m17n_object_unref (key_seq_list); +} +#endif + +int +minput_config_command (MSymbol language, MSymbol name, MSymbol command, + MPlist *keyseqlist) +{ + MInputMethodInfo *im_info, *config; + MPlist *plist; + + MINPUT__INIT (); + + im_info = get_im_info (language, name, Mnil, Mcommand); + if (! im_info) + MERROR (MERROR_IM, -1); + if (command == Mnil ? (keyseqlist && ! MPLIST_TAIL_P (keyseqlist)) + : (! im_info->cmds + || ! mplist__assq (im_info->configured_cmds, command))) + MERROR (MERROR_IM, -1); + if (keyseqlist && ! MPLIST_TAIL_P (keyseqlist)) + { + MPLIST_DO (plist, keyseqlist) + if (! check_command_keyseq (plist)) + MERROR (MERROR_IM, -1); + } + + config = get_config_info (im_info); + if (! config) + { + if (! im_config_list) + im_config_list = mplist (); + config = new_im_info (NULL, language, name, Mnil, im_config_list); + config->cmds = mplist (); + config->vars = mplist (); + } + + if (! keyseqlist && MPLIST_TAIL_P (config->cmds)) + /* Nothing to do. */ + return 0; + + if (command == Mnil) + { + if (! keyseqlist) + { + /* Cancal the configuration. */ + if (MPLIST_TAIL_P (config->cmds)) + return 0; + mplist_set (config->cmds, Mnil, NULL); + } + else + { + /* Cancal the customization. */ + MInputMethodInfo *custom = get_custom_info (im_info); + + if (MPLIST_TAIL_P (config->cmds) + && (! custom || ! custom->cmds || MPLIST_TAIL_P (custom->cmds))) + /* Nothing to do. */ + return 0; + mplist_set (config->cmds, Mnil, NULL); + MPLIST_DO (plist, custom->cmds) + { + command = MPLIST_SYMBOL (MPLIST_PLIST (plist)); + plist = mplist (); + mplist_add (plist, Msymbol, command); + mplist_push (config->cmds, Mplist, plist); + M17N_OBJECT_UNREF (plist); + } + } + } + else + { + plist = mplist__assq (config->cmds, command); + if (! keyseqlist) + { + /* Cancel the configuration. */ + if (! plist) + return 0; + mplist__pop_unref (plist); + } + else if (MPLIST_TAIL_P (keyseqlist)) + { + /* Cancel the customization. */ + MInputMethodInfo *custom = get_custom_info (im_info); + int no_custom = (! custom || ! custom->cmds + || ! mplist__assq (custom->cmds, command)); + if (! plist) + { + if (no_custom) + return 0; + plist = mplist (); + mplist_add (config->cmds, Mplist, plist); + M17N_OBJECT_UNREF (plist); + plist = mplist_add (plist, Msymbol, command); + } + else + { + if (no_custom) + mplist__pop_unref (plist); + else + { + plist = MPLIST_PLIST (plist); /* (NAME nil KEYSEQ ...) */ + plist = MPLIST_NEXT (plist); + mplist_set (plist, Mnil, NULL); + } + } + } + else + { + MPlist *pl; + + if (plist) + { + plist = MPLIST_NEXT (MPLIST_PLIST (plist)); + if (! MPLIST_TAIL_P (plist)) + mplist_set (plist, Mnil, NULL); + } + else + { + plist = mplist (); + mplist_add (config->cmds, Mplist, plist); + M17N_OBJECT_UNREF (plist); + plist = mplist_add (plist, Msymbol, command); + plist = MPLIST_NEXT (plist); + } + MPLIST_DO (keyseqlist, keyseqlist) + { + pl = mplist_copy (MPLIST_VAL (keyseqlist)); + plist = mplist_add (plist, Mplist, pl); + M17N_OBJECT_UNREF (pl); + } + } + } + config_all_commands (im_info); + im_info->tick = time (NULL); + return 0; +} + +/*=*/ + +/***en + @brief Get information about input method variable(s). + + The minput_get_variable () function returns information about + variable $VARIABLE of the input method specified by $LANGUAGE and $NAME. + An input method variable controls behavior of an input method. + + There are two kinds of variables, global and local. A global + variable has a global definition, and the description and the value + may be inherited by a local variable. Each input method defines a + local variable which has local value. It may also declare a + local variable that inherits definition of a global variable of + the same name. + + If $LANGUAGE is #Mt and $NAME is #Mnil, information about a global + variable is returned. Otherwise information about a local variable + is returned. + + If $VARIABLE is #Mnil, information about all variables is + returned. + + The return value is a @e well-formed plist (@ref m17nPlist) of this + format: +@verbatim + ((NAME DESCRIPTION STATUS VALUE [VALID-VALUE ...]) ...) +@endverbatim + @c NAME is a symbol representing the variable name. + + @c DESCRIPTION is an M-text describing the variable, or #Mnil if the + variable has no description. + + @c STATUS is a symbol representing how the value is decided. The + value is #Mnil (the default value), @b Mcustomized (the value is + customized by per-user customization file), or @b Mconfigured (the + value is set by the call of minput_config_variable ()). For a + local variable only, it may also be @b Minherited (the value is + inherited from the corresponding global variable). + + @c VALUE is the initial value of the variable. If the key of this + element is #Mt, the variable has no initial value. Otherwise, the + key is #Minteger, #Msymbol, or #Mtext and the value is of the + corresponding type. + + @c VALID-VALUEs (if any) specify which values the variable can have. + They have the same type (i.e. having the same key) as @c VALUE except + for the case that VALUE is an integer. In that case, @c VALID-VALUE + may be a plist of two integers specifying the range of possible + values. + + If there no @c VALID-VALUE, the variable can have any value as long + as the type is the same as @c VALUE. + + If $VARIABLE is not #Mnil, the first element of the returned plist + contains the information about $VARIABLE. + + @return + + If the requested information was found, a pointer to a non-empty + plist is returned. As the plist is kept in the library, the + caller must not modify nor free it. + + Otherwise (the specified input method or the specified variable + does not exist), @c NULL is returned. */ +/***ja + @brief ���ϥ᥽�åɤ��ѿ��˴ؤ�����������. + + �ؿ� minput_get_variable () �ϡ�$LANGUAGE �� $NAME �ǻ��ꤵ������� + �᥽�åɤ��ѿ� $VARIABLE �˴ؤ��������֤������ϥ᥽�åɤ��ѿ��Ȥϡ� + ���ϥ᥽�åɤο�������椹���ΤǤ��롣 + + �ѿ��ˤϡ��������Х�ȥ�������Σ����ब���롣�������Х���ѿ��ϥ� + �����Х��������졢����������ѿ��Ϥ����������ͤ�Ѿ����뤳�Ȥ��� + ���롣�����ϥ᥽�åɤϥ���������ͤ���ĥ���������ѿ���������롣 + �ޤ�Ʊ̾�Υ������Х���ѿ��������Ѿ��������������ѿ���������� + ���Ȥ�Ǥ��롣 + + $LANGUAGE �� #Mt �� $NAME �� #Mnil �ξ��ϡ����δؿ��ϥ������Х��� + ���˴ؤ��������֤��������Ǥʤ���Х��������ѿ��˴ؤ����Τ��֤��� + + $VARIABLE �� #Mnil �ξ��ϡ����٤ƤΥ��ޥ�ɤ˴ؤ��������֤��� + + ����ͤϰʲ��η����� @e well-formed plist (@ref m17nPlist) �Ǥ��롣 +@verbatim + ((NAME DESCRIPTION STATUS VALUE [VALID-VALUE ...]) ...) +@endverbatim + + @c NAME ���ѿ���̾���򼨤�����ܥ�Ǥ��롣 + + @c DESCRIPTION ���ѿ����������� M-text �Ǥ��뤫��������̵�����ˤ� + #Mnil �Ǥ��롣 + + @c STATUS ���ͤ��ɤΤ褦�������뤫�򤢤�魯����ܥ�Ǥ��ꡢ + @c STATUS ���ͤ� #Mnil �ʥǥե���Ȥ��͡�, @b Mcustomized �ʥ桼����� + �������ޥ����ե�����ˤ�äƥ������ޥ������줿�͡�, @b Mconfigured + ��minput_config_variable ()��Ƥ֤��Ȥˤ�ä����ꤵ����͡ˤΤ����� + ���Ǥ��롣���������ѿ��ξ��ˤϡ�@b Minherited ���б����륰�����Х� + �ѿ�����Ѿ������͡ˤǤ�褤�� + + @c VALUE ���ѿ��ν���ͤǤ��롣�������ǤΥ�����#Mt �Ǥ���н���ͤ�� + ���ʤ��������Ǥʤ���С������� #Minteger, #Msymbol, #Mtext �Τ����� + ���Ǥ��ꡢ�ͤϤ��줾���б����뷿�Τ�ΤǤ��롣 + + @c VALID-VALUE �Ϥ⤷����С��ѿ��μ�������ͤ���ꤹ�롣����� @c VALUE + ��Ʊ����(���ʤ��Ʊ�����������) �Ǥ��뤬���㳰�Ȥ��� @c VALUE �� + integer �ξ��� @c VALID-VALUE �ϲ�ǽ���ͤ��ϰϤ򼨤���Ĥ��������� + �ʤ� plist �Ȥʤ뤳�Ȥ��Ǥ��롣 + + @c VALID-VALUE ���ʤ���С��ѿ��� @c VALUE ��Ʊ�����Ǥ���¤ꤤ���ʤ��ͤ� + �Ȥ뤳�Ȥ��Ǥ��롣 + + $VARIABLE �� #Mnil �Ǥʤ���С��֤���� plist �κǽ�����Ǥ� + $VARIABLE �˴ؤ�������ޤࡣ + + @return + + ����줿���󤬸��Ĥ���С����Ǥʤ� plist �ؤΥݥ��󥿤��֤����ꥹ + �Ȥϥ饤�֥�꤬�������Ƥ���Τǡ��ƽ�¦���ѹ���������������ꤹ�� + ���ȤϤǤ��ʤ��� + + �����Ǥʤ���С����ʤ����������ϥ᥽�åɤ��ѿ���¸�ߤ��ʤ���� + @c NULL ���֤��� */ + +MPlist * +minput_get_variable (MSymbol language, MSymbol name, MSymbol variable) +{ + MInputMethodInfo *im_info; + + MINPUT__INIT (); + + im_info = get_im_info (language, name, Mnil, Mvariable); + if (! im_info || ! im_info->configured_vars) + return NULL; + if (variable == Mnil) + return im_info->configured_vars; + return mplist__assq (im_info->configured_vars, variable); +} + +/*=*/ + +/***en + @brief Configure the value of an input method variable. + + The minput_config_variable () function assigns $VALUE to the + variable $VARIABLE of the input method specified by $LANGUAGE and + $NAME. + + If $VALUE is a non-empty plist, it must be a plist of one element + whose key is #Minteger, #Msymbol, or #Mtext, and the value is of + the corresponding type. That value is assigned to the variable. + + If $VALUE is an empty plist, any configuration and customization + of the variable are canceled, and the default value is assigned to + the variable. + + If $VALUE is NULL, the configuration of the variable is canceled, + and the original value (what saved in per-user customization file, + or the default value) is assigned to the variable. + + In the latter two cases, $VARIABLE can be #Mnil to make all the + variables of the input method the target of the operation. + + If $NAME is #Mnil, this function configures the value of global + variable, not that of a specific input method. + + The configuration takes effect for input methods opened or + re-opened later in the current session. To make the configuration + take effect for the future session, it must be saved in a per-user + customization file by the function minput_save_config (). + + @return + + If the operation was successful, this function returns 0, + otherwise returns -1. The operation fails in these cases: +
    +
  • $VALUE is not in a valid form, the type does not match the + definition, or the value is our of range. +
  • $VARIABLE is not available for the input method. +
  • $LANGUAGE and $NAME do not specify an existing input method. +
+ + @seealso + minput_get_variable (), minput_save_config (). */ +/***ja + @brief ���ϥ᥽�åɤ��ѿ����ͤ����ꤹ��. + + �ؿ� minput_config_variable () ���� $VALUE ��$LANGUAGE �� $NAME + �ˤ�äƻ��ꤵ������ϥ᥽�åɤ��ѿ� $VARIABLE �˳�����Ƥ롣 + + $VALUE �� ���ꥹ�ȤǤʤ���С������Ǥ� plist �Ǥ��ꡢ���Υ����� + #Minteger, #Msymbol, #Mtext �Τ����줫���ͤ��б����뷿�Τ�ΤǤ��롣 + �����ͤ��ѿ� $VARIABLE �˳�����Ƥ��롣 + + $VALUE �� ���ꥹ�ȤǤ���С��ѿ�������ȥ������ޥ���������󥻥뤵 + �졢�ǥե�����ͤ��ѿ� $VARIABLE �˳�����Ƥ��롣 + + $VALUE �� NULL �Ǥ���С��ѿ�������ϥ���󥻥뤵�졢�����͡ʥ桼�� + ��Υ������ޥ����ե���������͡��ޤ��ϥǥե���Ȥ��͡ˤ�������Ƥ��롣 + + ��Τդ��Ĥξ��ˤϡ�$VARIABLE �� #Mnil ��Ȥ뤳�Ȥ��Ǥ������ꤵ�� + �����ϥ᥽�åɤ����Ƥ��ѿ�����Υ���󥻥���̣���롣 + + $NAME �� #Mnil �ʤ�С����δؿ��ϸġ������ϥ᥽�åɤǤϤʤ��������� + ����ѿ����ͤ����ꤹ�롣 + + ����������ϡ����ԤΥ��å����������ϥ᥽�åɤ������ץ�ʤޤ��� + �ƥ����ץ�ˤ��줿������ͭ���ˤʤ롣����Υ��å������Ǥ�ͭ���ˤ� + �뤿��ˤϡ��ؿ� minput_save_config () ���Ѥ��ƥ桼����Υ������ޥ� + ���ե��������¸���ʤ��ƤϤʤ�ʤ��� + + @return + + ���δؿ��ϡ���������������� 0 �򡢼��Ԥ���� -1 ���֤������ԤȤϰʲ��ξ��Ǥ��롣 +
    +
  • $VALUE��ͭ���ʷ����Ǥʤ�����������˹��ʤ����ޤ����ͤ��ϰϳ��Ǥ��롣 +
  • $VARIABLE ����������ϥ᥽�åɤ����ѤǤ��ʤ��� +
  • $LANGUAGE �� $NAME �ǻ��ꤵ������ϥ᥽�åɤ�¸�ߤ��ʤ��� +
+ + @seealso + minput_get_commands (), minput_save_config (). +*/ +int +minput_config_variable (MSymbol language, MSymbol name, MSymbol variable, + MPlist *value) +{ + MInputMethodInfo *im_info, *config; + MPlist *plist; + + MINPUT__INIT (); + + im_info = get_im_info (language, name, Mnil, Mvariable); + if (! im_info) + MERROR (MERROR_IM, -1); + if (variable == Mnil ? (value && ! MPLIST_TAIL_P (value)) + : (! im_info->vars + || ! (plist = mplist__assq (im_info->configured_vars, variable)))) + MERROR (MERROR_IM, -1); + + if (value && ! MPLIST_TAIL_P (value)) + { + plist = MPLIST_PLIST (plist); + plist = MPLIST_NEXT (plist); /* (DESC STATUS VALUE VALIDS ...) */ + plist = MPLIST_NEXT (plist); /* (STATUS VALUE VALIDS ...) */ + plist = MPLIST_NEXT (plist); /* (VALUE VALIDS ...) */ + if (MPLIST_KEY (plist) != Mt + && ! check_variable_value (value, plist)) + MERROR (MERROR_IM, -1); + } + + config = get_config_info (im_info); + if (! config) + { + if (! im_config_list) + im_config_list = mplist (); + config = new_im_info (NULL, language, name, Mnil, im_config_list); + config->cmds = mplist (); + config->vars = mplist (); + } + + if (! value && MPLIST_TAIL_P (config->vars)) + /* Nothing to do. */ + return 0; + + if (variable == Mnil) + { + if (! value) + { + /* Cancel the configuration. */ + if (MPLIST_TAIL_P (config->vars)) + return 0; + mplist_set (config->vars, Mnil, NULL); + } + else + { + /* Cancel the customization. */ + MInputMethodInfo *custom = get_custom_info (im_info); + + if (MPLIST_TAIL_P (config->vars) + && (! custom || ! custom->vars || MPLIST_TAIL_P (custom->vars))) + /* Nothing to do. */ + return 0; + mplist_set (config->vars, Mnil, NULL); + MPLIST_DO (plist, custom->vars) + { + variable = MPLIST_SYMBOL (MPLIST_PLIST (plist)); + plist = mplist (); + mplist_add (plist, Msymbol, variable); + mplist_push (config->vars, Mplist, plist); + M17N_OBJECT_UNREF (plist); + } + } + } + else + { + plist = mplist__assq (config->vars, variable); + if (! value) + { + /* Cancel the configuration. */ + if (! plist) + return 0; + mplist__pop_unref (plist); + } + else if (MPLIST_TAIL_P (value)) + { + /* Cancel the customization. */ + MInputMethodInfo *custom = get_custom_info (im_info); + int no_custom = (! custom || ! custom->vars + || ! mplist__assq (custom->vars, variable)); + if (! plist) + { + if (no_custom) + return 0; + plist = mplist (); + mplist_add (config->vars, Mplist, plist); + M17N_OBJECT_UNREF (plist); + plist = mplist_add (plist, Msymbol, variable); + } + else + { + if (no_custom) + mplist__pop_unref (plist); + else + { + plist = MPLIST_PLIST (plist); /* (NAME nil VALUE) */ + plist = MPLIST_NEXT (plist); /* ([nil VALUE]) */ + mplist_set (plist, Mnil ,NULL); + } + } + } + else + { + if (plist) + { + plist = MPLIST_NEXT (MPLIST_PLIST (plist)); + if (! MPLIST_TAIL_P (plist)) + mplist_set (plist, Mnil, NULL); + } + else + { + plist = mplist (); + mplist_add (config->vars, Mplist, plist); + M17N_OBJECT_UNREF (plist); + plist = mplist_add (plist, Msymbol, variable); + plist = MPLIST_NEXT (plist); + } + mplist_add (plist, MPLIST_KEY (value), MPLIST_VAL (value)); + } + } + config_all_variables (im_info); + im_info->tick = time (NULL); + return 0; +} + +/*=*/ + +/***en + @brief Get the name of per-user customization file. + + The minput_config_file () function returns the absolute path name + of per-user customization file into which minput_save_config () + save configurations. It is usually @c config.mic under the + directory ${HOME}/.m17n.d (${HOME} is user's home + directory). It is not assured that the file of the returned name + exists nor is readable/writable. If minput_save_config () fails + and returns -1, an application program might check the file, make + it writable (if possible), and try minput_save_config () again. + + @return + + This function returns a string. As the string is kept in the + library, the caller must not modify nor free it. + + @seealso + minput_save_config () +*/ +/***ja + @brief �桼����Υ������ޥ����ե������̾��������. + + �ؿ� minput_config_file () �ϡ��ؿ� minput_save_config () ������� + ��¸����桼����Υ������ޥ����ե�����ؤ����Хѥ�̾���֤����̾�ϡ��桼�� + �Υۡ���ǥ��쥯�ȥ�β��Υǥ��쥯�ȥ� @c ".m17n.d" �ˤ���@c + "config.mic" �Ȥʤ롣�֤��줿̾���Υե����뤬¸�ߤ��뤫���ɤ߽񤭤� + ���뤫���ݾڤ���ʤ����ؿ�minput_save_config () �����Ԥ��� -1 ���� + �������ˤϡ����ץꥱ�������ץ������ϥե������¸�ߤ��ǧ���� + �ʤǤ���С˽񤭹��߲�ǽ�ˤ�����minput_save_config () �����Ȥ� + �Ǥ��롣 + + @return + + ���δؿ���ʸ������֤���ʸ����ϥ饤�֥�꤬�������Ƥ���Τǡ��ƽ� + ¦��������������������ꤹ�뤳�ȤϤǤ��ʤ��� + + @seealso + minput_save_config () +*/ + +char * +minput_config_file () +{ + MINPUT__INIT (); + + return mdatabase__file (im_custom_mdb); +} + +/*=*/ + +/***en + @brief Save configurations in per-user customization file. + + The minput_save_config () function saves the configurations done + so far in the current session into the per-user customization + file. + + @return + + If the operation was successful, 1 is returned. If the per-user + customization file is currently locked, 0 is returned. In that + case, the caller may wait for a while and try again. If the + configuration file is not writable, -1 is returned. In that case, + the caller may check the name of the file by calling + minput_config_file (), make it writable if possible, and try + again. + + @seealso + minput_config_file () */ +/***ja + @brief �����桼����Υ������ޥ����ե��������¸����. + + �ؿ� minput_save_config () �ϸ��ԤΥ��å����Ǥ���ޤǤ˹Ԥä����� + ��桼����Υ������ޥ����ե��������¸���롣 + + @return + + ��������� 1 ���֤����桼����Υ������ޥ����ե����뤬���å�����Ƥ� + ��� 0 ���֤������ξ�硢�ƽ�¦�Ϥ��Ф餯�Ԥäƺƻ�ԤǤ��롣����ե� + ���뤬�񤭹����ԲĤξ�硢-1 ���֤������ξ�硢minput_config_file + () ��Ƥ�ǥե�����̾������å������Ǥ���н񤭹��߲�ǽ�ˤ����ƻ�� + �Ǥ��롣 + + @seealso + minput_config_file () */ + +int +minput_save_config (void) +{ + MPlist *data, *tail, *plist, *p, *elt; + int ret; + + MINPUT__INIT (); + ret = mdatabase__lock (im_custom_mdb); + if (ret <= 0) + return ret; + if (! im_config_list) + return 1; + update_custom_info (); + if (! im_custom_list) + im_custom_list = mplist (); + + /* At first, reflect configuration in customization. */ + MPLIST_DO (plist, im_config_list) + { + MPlist *pl = MPLIST_PLIST (plist); + MSymbol language, name, extra, command, variable; + MInputMethodInfo *custom, *config; + + language = MPLIST_SYMBOL (pl); + pl = MPLIST_NEXT (pl); + name = MPLIST_SYMBOL (pl); + pl = MPLIST_NEXT (pl); + extra = MPLIST_SYMBOL (pl); + pl = MPLIST_NEXT (pl); + config = MPLIST_VAL (pl); + custom = get_custom_info (config); + if (! custom) + custom = new_im_info (NULL, language, name, extra, im_custom_list); + if (config->cmds) + MPLIST_DO (pl, config->cmds) + { + elt = MPLIST_PLIST (pl); + command = MPLIST_SYMBOL (elt); + if (custom->cmds) + p = mplist__assq (custom->cmds, command); + else + custom->cmds = mplist (), p = NULL; + elt = MPLIST_NEXT (elt); + if (p) + { + p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p))); + mplist_set (p, Mnil, NULL); + } + else + { + p = mplist (); + mplist_add (custom->cmds, Mplist, p); + M17N_OBJECT_UNREF (p); + mplist_add (p, Msymbol, command); + p = mplist_add (p, Msymbol, Mnil); + p = MPLIST_NEXT (p); + } + mplist__conc (p, elt); + } + if (config->vars) + MPLIST_DO (pl, config->vars) + { + elt = MPLIST_PLIST (pl); + variable = MPLIST_SYMBOL (elt); + if (custom->vars) + p = mplist__assq (custom->vars, variable); + else + custom->vars = mplist (), p = NULL; + elt = MPLIST_NEXT (elt); + if (p) + { + p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (p))); + mplist_set (p, Mnil, NULL); + } + else + { + p = mplist (); + mplist_add (custom->vars, Mplist, p); + M17N_OBJECT_UNREF (p); + mplist_add (p, Msymbol, variable); + p = mplist_add (p, Msymbol, Mnil); + p = MPLIST_NEXT (p); + } + mplist__conc (p, elt); + } + } + free_im_list (im_config_list); + im_config_list = NULL; + + /* Next, reflect customization to the actual plist to be written. */ + data = tail = mplist (); + MPLIST_DO (plist, im_custom_list) + { + MPlist *pl = MPLIST_PLIST (plist); + MSymbol language, name, extra; + MInputMethodInfo *custom, *im_info; + + language = MPLIST_SYMBOL (pl); + pl = MPLIST_NEXT (pl); + name = MPLIST_SYMBOL (pl); + pl = MPLIST_NEXT (pl); + extra = MPLIST_SYMBOL (pl); + pl = MPLIST_NEXT (pl); + custom = MPLIST_VAL (pl); + if ((! custom->cmds || MPLIST_TAIL_P (custom->cmds)) + && (! custom->vars || MPLIST_TAIL_P (custom->vars))) + continue; + im_info = lookup_im_info (im_info_list, language, name, extra); + if (im_info) + { + if (im_info->cmds) + config_all_commands (im_info); + if (im_info->vars) + config_all_variables (im_info); + } + + elt = NULL; + if (custom->cmds && ! MPLIST_TAIL_P (custom->cmds)) + { + MPLIST_DO (p, custom->cmds) + if (! MPLIST_TAIL_P (MPLIST_NEXT (MPLIST_PLIST (p)))) + break; + if (! MPLIST_TAIL_P (p)) + { + elt = mplist (); + pl = mplist (); + mplist_add (elt, Mplist, pl); + M17N_OBJECT_UNREF (pl); + pl = mplist_add (pl, Msymbol, Mcommand); + MPLIST_DO (p, custom->cmds) + if (! MPLIST_TAIL_P (MPLIST_NEXT (MPLIST_PLIST (p)))) + pl = mplist_add (pl, Mplist, MPLIST_PLIST (p)); + } + } + if (custom->vars && ! MPLIST_TAIL_P (custom->vars)) + { + MPLIST_DO (p, custom->vars) + if (! MPLIST_TAIL_P (MPLIST_NEXT (MPLIST_PLIST (p)))) + break; + if (! MPLIST_TAIL_P (p)) + { + if (! elt) + elt = mplist (); + pl = mplist (); + mplist_add (elt, Mplist, pl); + M17N_OBJECT_UNREF (pl); + pl = mplist_add (pl, Msymbol, Mvariable); + MPLIST_DO (p, custom->vars) + if (! MPLIST_TAIL_P (MPLIST_NEXT (MPLIST_PLIST (p)))) + pl = mplist_add (pl, Mplist, MPLIST_PLIST (p)); + } + } + if (elt) + { + pl = mplist (); + mplist_push (elt, Mplist, pl); + M17N_OBJECT_UNREF (pl); + pl = mplist_add (pl, Msymbol, Minput_method); + pl = mplist_add (pl, Msymbol, language); + pl = mplist_add (pl, Msymbol, name); + if (extra != Mnil) + pl = mplist_add (pl, Msymbol, extra); + tail = mplist_add (tail, Mplist, elt); + M17N_OBJECT_UNREF (elt); + } + } + + mplist_push (data, Mstring, ";; -*- mode:lisp; coding:utf-8 -*-"); + ret = mdatabase__save (im_custom_mdb, data); + mdatabase__unlock (im_custom_mdb); + M17N_OBJECT_UNREF (data); + return (ret < 0 ? -1 : 1); +} + +/***en + @brief List available input methods. + + The minput_list () function returns a list of currently available + input methods whose language is $LANGUAGE. If $LANGUAGE is #Mnil, + all input methods are listed. + + @return + The returned value is a plist of this form: + ((LANGUAGE-NAME INPUT-METHOD-NAME SANE) ...) + The third element SANE of each input method is #Mt if it can be + successfully used, or #Mnil if it has some problem (e.g. syntax + error of MIM file, unavailable external module, unavailable + including input method). */ + +#if EXAMPLE_CODE +#include +#include +#include + +int +main (int argc, char **argv) +{ + MPlist *imlist, *pl; + + M17N_INIT (); + imlist = minput_list ((argc > 1) ? msymbol (argv[1]) : Mnil); + for (pl = imlist; mplist_key (pl) != Mnil; pl = mplist_next (pl)) + { + MPlist *p = mplist_value (pl); + MSymbol lang, name, sane; + + lang = mplist_value (p); + p = mplist_next (p); + name = mplist_value (p); + p = mplist_next (p); + sane = mplist_value (p); + + printf ("%s %s %s\n", msymbol_name (lang), msymbol_name (name), + sane == Mt ? "ok" : "no"); + } + + m17n_object_unref (imlist); + M17N_FINI (); + exit (0); +} +#endif + +MPlist * +minput_list (MSymbol language) +{ + MPlist *plist, *pl; + MPlist *imlist = mplist (); + + MINPUT__INIT (); + plist = mdatabase_list (Minput_method, language, Mnil, Mnil); + if (! plist) + return imlist; + MPLIST_DO (pl, plist) + { + MDatabase *mdb = MPLIST_VAL (pl); + MSymbol *tag = mdatabase_tag (mdb); + MPlist *imdata, *p, *elm; + int num_maps = 0, num_states = 0; + + if (tag[2] == Mnil) + continue; + imdata = mdatabase_load (mdb); + if (! imdata) + continue; + MPLIST_DO (p, imdata) + if (MPLIST_PLIST_P (p)) + { + /* Check these basic functionarity: + All external modules (if any) are loadable. + All included input method (if any) are loadable. + At least one map is defined or included. + At least one state is defined or included. */ + MPlist *elt = MPLIST_PLIST (p); + MSymbol key; + + if (MFAILP (MPLIST_SYMBOL_P (elt))) + break; + key = MPLIST_SYMBOL (elt); + if (key == Mmap) + num_maps++; + else if (key == Mstate) + num_states++; + else if (key == Mmodule) + { + MPLIST_DO (elt, MPLIST_NEXT (elt)) + { + MIMExternalModule *external; + + if (MFAILP (MPLIST_PLIST_P (elt))) + break; + external = load_external_module (MPLIST_PLIST (elt)); + if (MFAILP (external)) + break; + unload_external_module (external); + } + if (! MPLIST_TAIL_P (elt)) + break; + } + else if (key == Minclude) + { + MInputMethodInfo *im_info; + + elt = MPLIST_NEXT (elt); + if (MFAILP (MPLIST_PLIST_P (elt))) + break; + im_info = get_im_info_by_tags (MPLIST_PLIST (elt)); + if (MFAILP (im_info)) + break; + elt = MPLIST_NEXT (elt); + if (MFAILP (MPLIST_SYMBOL_P (elt))) + break; + key = MPLIST_SYMBOL (elt); + if (key == Mmap) + { + if (! im_info->maps) + break; + num_maps++; + } + else if (key == Mstate) + { + if (! im_info->states) + break; + num_states++; + } + } + } + elm = mplist (); + mplist_add (elm, Msymbol, tag[1]); + mplist_add (elm, Msymbol, tag[2]); + if (MPLIST_TAIL_P (p) && num_maps > 0 && num_states > 0) + mplist_add (elm, Msymbol, Mt); + else + mplist_add (elm, Msymbol, Mnil); + mplist_push (imlist, Mplist, elm); + M17N_OBJECT_UNREF (elm); + M17N_OBJECT_UNREF (imdata); + } + M17N_OBJECT_UNREF (plist); + return imlist; +} + +/*=*/ +/*** @} */ +/*=*/ +/***en + @name Obsolete functions +*/ +/***ja + @name Obsolete �ʴؿ� +*/ +/*** @{ */ + +/*=*/ +/***en + @brief Get a list of variables of an input method (obsolete). + + This function is obsolete. Use minput_get_variable () instead. + + The minput_get_variables () function returns a plist (#MPlist) of + variables used to control the behavior of the input method + specified by $LANGUAGE and $NAME. The plist is @e well-formed + (@ref m17nPlist) of the following format: + +@verbatim + (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] ) + VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] ) + ...) +@endverbatim + + @c VARNAME is a symbol representing the variable name. + + @c DOC-MTEXT is an M-text describing the variable. + + @c DEFAULT-VALUE is the default value of the variable. It is a + symbol, integer, or M-text. + + @c VALUEs (if any) specifies the possible values of the variable. + If @c DEFAULT-VALUE is an integer, @c VALUE may be a plist (@c FROM + @c TO), where @c FROM and @c TO specifies a range of possible + values. + + For instance, suppose an input method has the variables: + + @li name:intvar, description:"value is an integer", + initial value:0, value-range:0..3,10,20 + + @li name:symvar, description:"value is a symbol", + initial value:nil, value-range:a, b, c, nil + + @li name:txtvar, description:"value is an M-text", + initial value:empty text, no value-range (i.e. any text) + + Then, the returned plist is as follows. + +@verbatim + (intvar ("value is an integer" 0 (0 3) 10 20) + symvar ("value is a symbol" nil a b c nil) + txtvar ("value is an M-text" "")) +@endverbatim + + @return + If the input method uses any variables, a pointer to #MPlist is + returned. As the plist is kept in the library, the caller must not + modify nor free it. If the input method does not use any + variable, @c NULL is returned. */ +/***ja + @brief ���ϥ᥽�åɤ��ѿ��ꥹ�Ȥ�����. + + �ؿ� minput_get_variables () �ϡ�$LANGUAGE �� $NAME �ˤ�äƻ��ꤵ + �줿���ϥ᥽�åɤο����񤤤����椹���ѿ��Υץ��ѥƥ��ꥹ�� + (#MPlist) ���֤������Υꥹ�Ȥ� @e well-formed �Ǥ���(@ref m17nPlist) �� + ���η����Ǥ��롣 + +@verbatim + (VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] ) + VARNAME (DOC-MTEXT DEFAULT-VALUE [ VALUE ... ] ) + ...) +@endverbatim + + @c VARNAME ���ѿ���̾���򼨤�����ܥ�Ǥ��롣 + + @c DOC-MTEXT ���ѿ����������� M-text �Ǥ��롣 + + @c DEFAULT-VALUE ���ѿ��Υǥե�����ͤǤ��ꡢ����ܥ롢�����⤷���� + M-text �Ǥ��롣 + + @c VALUE �ϡ��⤷���ꤵ��Ƥ�����ѿ��μ�������ͤ򼨤����⤷ + @c DEFAULT-VALUE �������ʤ顢 @c VALUE �� (@c FROM @c TO) �Ȥ����� + �Υꥹ�ȤǤ��ɤ������ξ�� @c FROM �� @c TO �ϲ�ǽ���ͤ��ϰϤ򼨤��� + + ��Ȥ��ơ��������ϥ᥽�åɤ����Τ褦���ѿ�����ľ���ͤ��褦�� + + @li name:intvar, ����:"value is an integer", + �����:0, �ͤ��ϰ�:0..3,10,20 + + @li name:symvar, ����:"value is a symbol", + �����:nil, �ͤ��ϰ�:a, b, c, nil + + @li name:txtvar, ����:"value is an M-text", + �����:empty text, �ͤ��ϰϤʤ�(�ɤ�� M-text �Ǥ��) + + ���ξ�硢�֤����ꥹ�Ȥϰʲ��Τ褦�ˤʤ롣 + +@verbatim + (intvar ("value is an integer" 0 (0 3) 10 20) + symvar ("value is a symbol" nil a b c nil) + txtvar ("value is an M-text" "")) +@endverbatim + + @return + ���ϥ᥽�åɤ����餫���ѿ�����Ѥ��Ƥ���� #MPlist �ؤΥݥ��󥿤��֤��� + �֤����ץ��ѥƥ��ꥹ�Ȥϥ饤�֥��ˤ�äƴ�������Ƥ��ꡢ�ƤӽФ�¦���ѹ���������������ꤷ�ƤϤʤ�ʤ��� + ���ϥ᥽�åɤ��ѿ�����ڻ��Ѥ��Ƥʤ���С�@c NULL ���֤��� */ + +MPlist * +minput_get_variables (MSymbol language, MSymbol name) +{ + MInputMethodInfo *im_info; + MPlist *vars; + + MINPUT__INIT (); + + im_info = get_im_info (language, name, Mnil, Mvariable); + if (! im_info || ! im_info->configured_vars) + return NULL; + + M17N_OBJECT_UNREF (im_info->bc_vars); + im_info->bc_vars = mplist (); + MPLIST_DO (vars, im_info->configured_vars) + { + MPlist *plist = MPLIST_PLIST (vars); + MPlist *elt = mplist (); + + mplist_push (im_info->bc_vars, Mplist, elt); + mplist_add (elt, Msymbol, MPLIST_SYMBOL (plist)); + elt = MPLIST_NEXT (elt); + mplist_set (elt, Mplist, mplist_copy (MPLIST_NEXT (plist))); + M17N_OBJECT_UNREF (elt); + } + return im_info->bc_vars; +} + +/*=*/ + +/***en + @brief Set the initial value of an input method variable. + + The minput_set_variable () function sets the initial value of + input method variable $VARIABLE to $VALUE for the input method + specified by $LANGUAGE and $NAME. + + By default, the initial value is 0. + + This setting gets effective in a newly opened input method. + + @return + If the operation was successful, 0 is returned. Otherwise -1 is + returned, and #merror_code is set to @c MERROR_IM. */ +/***ja + @brief ���ϥ᥽�å��ѿ��ν���ͤ����ꤹ��. + + �ؿ� minput_set_variable () �ϡ�$LANGUAGE �� $NAME + �ˤ�äƻ��ꤵ�줿���ϥ᥽�åɤ����ϥ᥽�å��ѿ� $VARIABLE + �ν���ͤ� $VALUE �����ꤹ�롣 + + �ǥե���Ȥν���ͤ� 0 �Ǥ��롣 + + ��������ϡ������������ץ󤵤줿���ϥ᥽�åɤ���ͭ���Ȥʤ롣 + + @return + ��������������� 0 ���֤��������Ǥʤ���� -1 ���֤��� + #merror_code �� @c MERROR_IM �����ꤹ�롣 */ + +int +minput_set_variable (MSymbol language, MSymbol name, + MSymbol variable, void *value) +{ + MPlist *plist, *pl; + MInputMethodInfo *im_info; + int ret; + + MINPUT__INIT (); + + if (variable == Mnil) + MERROR (MERROR_IM, -1); + plist = minput_get_variable (language, name, variable); + plist = MPLIST_PLIST (plist); + plist = MPLIST_NEXT (plist); + pl = mplist (); + mplist_add (pl, MPLIST_KEY (plist), value); + ret = minput_config_variable (language, name, variable, pl); + M17N_OBJECT_UNREF (pl); + if (ret == 0) + { + im_info = get_im_info (language, name, Mnil, Mvariable); + im_info->tick = 0; + } + return ret; +} + +/*=*/ + +/***en + @brief Get information about input method commands. + + The minput_get_commands () function returns information about + input method commands of the input method specified by $LANGUAGE + and $NAME. An input method command is a pseudo key event to which + one or more actual input key sequences are assigned. + + There are two kinds of commands, global and local. Global + commands are used by multiple input methods for the same purpose, + and have global key assignments. Local commands are used only by + a specific input method, and have only local key assignments. + + Each input method may locally change key assignments for global + commands. The global key assignment for a global command is + effective only when the current input method does not have local + key assignments for that command. + + If $NAME is #Mnil, information about global commands is returned. + In this case $LANGUAGE is ignored. + + If $NAME is not #Mnil, information about those commands that have + local key assignments in the input method specified by $LANGUAGE + and $NAME is returned. + + @return + If no input method commands are found, this function returns @c NULL. + + Otherwise, a pointer to a plist is returned. The key of each + element in the plist is a symbol representing a command, and the + value is a plist of the form COMMAND-INFO described below. + + The first element of COMMAND-INFO has the key #Mtext, and the + value is an M-text describing the command. + + If there are no more elements, that means no key sequences are + assigned to the command. Otherwise, each of the remaining + elements has the key #Mplist, and the value is a plist whose keys are + #Msymbol and values are symbols representing input keys, which are + currently assigned to the command. + + As the returned plist is kept in the library, the caller must not + modify nor free it. */ +/***ja + @brief ���ϥ᥽�åɤΥ��ޥ�ɤ˴ؤ�����������. + + �ؿ� minput_get_commands () �ϡ� $LANGUAGE �� $NAME �ˤ�äƻ��ꤵ + �줿���ϥ᥽�åɤ����ϥ᥽�åɥ��ޥ�ɤ˴ؤ��������֤������ϥ᥽�� + �ɥ��ޥ�ɤȤϡ������������٥�ȤǤ��ꡢ���줾��ˣ��İʾ�μºݤ� + ���ϥ������������󥹤�������Ƥ��Ƥ����Τ�ؤ��� + + ���ޥ�ɤˤϥ������Х�ȥ�������Σ����ब���롣�������Х륳�ޥ�� + ��ʣ�������ϥ᥽�åɤˤ����ơ�Ʊ����Ū�ǡ��������Х�ʥ���������� + ���Ѥ����롣�������륳�ޥ�ɤ���������ϥ᥽�åɤǤΤߡ��������� + �ʥ��������ǻ��Ѥ���롣 + + �ġ������ϥ᥽�åɤϥ������Х륳�ޥ�ɤΥ����������ѹ����뤳�Ȥ�� + ���롣�������Х륳�ޥ���ѤΥ������Х륭��������Ƥϡ����Ѥ������� + �᥽�åɤˤ����Ƥ��Υ��ޥ���ѤΥ�������ʥ���������¸�ߤ��ʤ���� + �ˤΤ�ͭ���Ǥ��롣 + + $NAME �� #Mnil �Ǥ���С��������Х륳�ޥ�ɤ˴ؤ��������֤������� + ��硢$LANGUAGE ��̵�뤵��롣 + + $NAME �� #Mnil �Ǥʤ���С�$LANGUAGE �� $NAME �ˤ�äƻ��ꤵ����� + �ϥ᥽�åɤ��֤����������ʥ���������Ƥ���ĥ��ޥ�ɤ˴ؤ������ + ���֤��� + + @return + ���ϥ᥽�åɥ��ޥ�ɤ����Ĥ���ʤ���С����δؿ��� @c NULL ���֤��� + + �����Ǥʤ���Хץ��ѥƥ��ꥹ�ȤؤΥݥ��󥿤��֤����ꥹ�Ȥγ����Ǥ� + �����ϸġ��Υ��ޥ�ɤ򼨤�����ܥ�Ǥ��ꡢ�ͤϲ����� COMMAND-INFO + �η����Υץ��ѥƥ��ꥹ�ȤǤ��롣 + + COMMAND-INFO ��������ǤΥ����� #Mtext �ޤ��� #Msymbol �Ǥ��롣���� + �� #Mtext �ʤ顢�ͤϤ��Υ��ޥ�ɤ��������� M-text �Ǥ��롣������ + #Msymbol �ʤ��ͤ� #Mnil �Ǥ��ꡢ���Υ��ޥ�ɤ������ƥ����Ȥ������ + �����Ȥˤʤ롣 + + ����ʳ������Ǥ�̵����С����Υ��ޥ�ɤ��Ф��ƥ������������󥹤��� + �����Ƥ��Ƥ��ʤ����Ȥ��̣���롣�����Ǥʤ���С��Ĥ�γ����Ǥϥ� + ���Ȥ���#Mplist ���ͤȤ��ƥץ��ѥƥ��ꥹ�Ȥ���ġ����Υץ��ѥƥ� + �ꥹ�ȤΥ����� #Msymbol �Ǥ��ꡢ�ͤϸ��ߤ��Υ��ޥ�ɤ˳�����Ƥ�� + �Ƥ������ϥ�����ɽ������ܥ�Ǥ��롣 + + �֤����ץ��ѥƥ��ꥹ�Ȥϥ饤�֥��ˤ�äƴ�������Ƥ��ꡢ�Ƥӽ� + ��¦���ѹ���������������ꤷ�ƤϤʤ�ʤ���*/ + +MPlist * +minput_get_commands (MSymbol language, MSymbol name) +{ + MInputMethodInfo *im_info; + MPlist *cmds; + + MINPUT__INIT (); + + im_info = get_im_info (language, name, Mnil, Mcommand); + if (! im_info || ! im_info->configured_vars) + return NULL; + M17N_OBJECT_UNREF (im_info->bc_cmds); + im_info->bc_cmds = mplist (); + MPLIST_DO (cmds, im_info->configured_cmds) + { + MPlist *plist = MPLIST_PLIST (cmds); + MPlist *elt = mplist (); + + mplist_push (im_info->bc_cmds, Mplist, elt); + mplist_add (elt, MPLIST_SYMBOL (plist), + mplist_copy (MPLIST_NEXT (plist))); + M17N_OBJECT_UNREF (elt); + } + return im_info->bc_cmds; +} + +/*=*/ + +/***en + @brief Assign a key sequence to an input method command (obsolete). + + This function is obsolete. Use minput_config_command () instead. + + The minput_assign_command_keys () function assigns input key + sequence $KEYSEQ to input method command $COMMAND for the input + method specified by $LANGUAGE and $NAME. If $NAME is #Mnil, the + key sequence is assigned globally no matter what $LANGUAGE is. + Otherwise the key sequence is assigned locally. + + Each element of $KEYSEQ must have the key $Msymbol and the value + must be a symbol representing an input key. + + $KEYSEQ may be @c NULL, in which case, all assignments are deleted + globally or locally. + + This assignment gets effective in a newly opened input method. + + @return + If the operation was successful, 0 is returned. Otherwise -1 is + returned, and #merror_code is set to @c MERROR_IM. */ +/***ja + @brief ���ϥ᥽�åɥ��ޥ�ɤ˥������������󥹤������Ƥ�. + + �ؿ� minput_assign_command_keys () �ϡ� $LANGUAGE �� $NAME �ˤ�ä� + ���ꤵ�줿���ϥ᥽�å��Ѥ����ϥ᥽�åɥ��ޥ�� $COMMAND ���Ф��ơ� + ���ϥ������������� $KEYSEQ �������Ƥ롣 $NAME �� #Mnil �ʤ�С� + $LANGUAGE �˴ط��ʤ������ϥ������������󥹤ϥ������Х�˳�����Ƥ� + ��롣�����Ǥʤ�С�������Ƥϥ�������Ǥ��롣 + + $KEYSEQ �γ����Ǥϥ����Ȥ��� $Msymbol ���ͤȤ������ϥ�����ɽ���� + ��ܥ������ʤ��ƤϤʤ�ʤ��� + + $KEYSEQ �� @c NULL �Ǥ�褤�����ξ�硢�������Х�⤷���ϥ�������� + ���٤Ƥγ�����Ƥ��õ��롣 + + ���γ�����Ƥϡ�������ưʹ߿����������ץ󤵤줿���ϥ᥽�åɤ���ͭ + ���ˤʤ롣 + + @return + ��������������� 0 ���֤��������Ǥʤ���� -1 ���֤��� + #merror_code �� @c MERROR_IM �����ꤹ�롣 */ + +int +minput_assign_command_keys (MSymbol language, MSymbol name, + MSymbol command, MPlist *keyseq) +{ + int ret; + + MINPUT__INIT (); + + if (command == Mnil) + MERROR (MERROR_IM, -1); + if (keyseq) + { + MPlist *plist; + + if (! check_command_keyseq (keyseq)) + MERROR (MERROR_IM, -1); + plist = mplist (); + mplist_add (plist, Mplist, keyseq); + keyseq = plist; + } + else + keyseq = mplist (); + ret = minput_config_command (language, name, command, keyseq); + M17N_OBJECT_UNREF (keyseq); + return ret; +} + +/*=*/ + +/***en + @brief Parse input method names + + The minput_parse_im_names () function parses M-text $MT and returns + a list of input method names. Input method names in $MT must be + separated by comma (","). Input methods whose language is #Mt can + be specified by its name only (i.e. just "latn-post" instead of + "t-latn-post"). + + @return + The minput_parse_im_names () returns a plist of which elements are + plist of LANGUAGE and NAME of input methods as below: + ((LANGUAGE1 NAME1) (LANGUAGE2 NAME2) ...) + Both LANGUAGEn and NAMEn are symbols. LANGUAGEn is #Mt if the + corresponding input method is not limited to a specific language. + If a specified input method doesn't exist, the corresponding + element in the above plist is a sub-part of $MT for that + non-existing input method name. + For instance, if "symbol,unknown,unicode" is specified as $MT and + "unknown" doesn't exist, the return value is: + ((t symbol) "unknown" (t unicode)) + */ + +MPlist * +minput_parse_im_names (MText *mt) +{ + int from = 0, to = mtext_len (mt), i, start = 0; + MPlist *plist = mplist ();; + char *buf; + + MINPUT__INIT (); + + MTABLE_MALLOC (buf, to + 1, MERROR_IM); + i = 0; + while (1) + { + MSymbol lang = Mnil, name = Mnil; + int c; + int idx = 0, name_idx = 0; + MInputMethodInfo *im_info; + + while (i < to && ((c = mtext_ref_char (mt, i)) == ' ' || c >= 128)) + i++; + if (i >= to) + break; + buf[idx++] = c; + i++; + while (i < to && ((c = mtext_ref_char (mt, i)) != ',' && c != ' ')) + { + if (c == '-' && name_idx == 0) + { + buf[idx] = '\0'; + lang = msymbol (buf); + name_idx = idx + 1; + } + buf[idx++] = c; + i++; + } + buf[idx] = '\0'; + name = msymbol (buf + name_idx); + if (name_idx == 0) + lang = Mt; + + im_info = get_im_info (lang, name, Mnil, Mnil); + if (! im_info && lang != Mt) + { + lang = Mt; + name = msymbol (buf); + im_info = get_im_info (lang, name, Mnil, Mnil); + } + if (im_info) + { + MPlist *p = mplist (); + + mplist_add (p, Msymbol, lang); + mplist_add (p, Msymbol, name); + mplist_add (plist, Mplist, p); + M17N_OBJECT_UNREF (p); + } + else + { + MText *err = mtext__from_data (buf, idx, MTEXT_FORMAT_US_ASCII, 1); + mplist_add (plist, Mtext, err); + M17N_OBJECT_UNREF (err); + } + i++; + } + free (buf); + return plist; +} + + +/*=*/ + +/***en + @brief Call a callback function + + The minput_callback () functions calls a callback function + $COMMAND assigned for the input context $IC. The caller must set + specific elements in $IC->plist if the callback function requires. + + @return + If there exists a specified callback function, 0 is returned. + Otherwise -1 is returned. By side effects, $IC->plist may be + modified. */ + +int +minput_callback (MInputContext *ic, MSymbol command) +{ + MInputCallbackFunc func; + + if (! ic->im->driver.callback_list) + return -1; + func = ((MInputCallbackFunc) + mplist_get_func (ic->im->driver.callback_list, command)); + if (! func) + return -1; + (func) (ic, command); + return 0; +} + +/*** @} */ +/*** @} */ +/*=*/ +/*** @addtogroup m17nDebug */ +/*=*/ +/*** @{ */ +/*=*/ + +/***en + @brief Dump an input method. + + The mdebug_dump_im () function prints the input method $IM in a + human readable way to the stderr or to what specified by the + environment variable MDEBUG_OUTPUT_FILE. $INDENT specifies how + many columns to indent the lines but the first one. + + @return + This function returns $IM. */ +/***ja + @brief ���ϥ᥽�åɤ����פ���. + + �ؿ� mdebug_dump_im () �����ϥ᥽�å� $IM ��ɸ�२�顼���Ϥ⤷���� + �Ķ��ѿ� MDEBUG_DUMP_FONT �ǻ��ꤵ�줿�ե�����˿ʹ֤˲��ɤʷ��ǽ� + �Ϥ��롣$INDENT �ϣ����ܰʹߤΥ���ǥ�Ȥ���ꤹ�롣 + + @return + ���δؿ��� $IM ���֤��� */ + +MInputMethod * +mdebug_dump_im (MInputMethod *im, int indent) +{ + MInputMethodInfo *im_info = (MInputMethodInfo *) im->info; + char *prefix; + + prefix = (char *) alloca (indent + 1); + memset (prefix, 32, indent); + prefix[indent] = '\0'; + + fprintf (mdebug__output, "(input-method %s %s ", msymbol_name (im->language), + msymbol_name (im->name)); + mdebug_dump_mtext (im_info->title, 0, 0); + if (im->name != Mnil) + { + MPlist *state; + + MPLIST_DO (state, im_info->states) + { + fprintf (mdebug__output, "\n%s ", prefix); + dump_im_state (MPLIST_VAL (state), indent + 2); + } + } + fprintf (mdebug__output, ")"); + return im; +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/input.h b/src/input.h new file mode 100644 index 0000000..c182d9b --- /dev/null +++ b/src/input.h @@ -0,0 +1,116 @@ +/* input.h -- header file for the input method module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_INPUT_H_ +#define _M17N_INPUT_H_ + +typedef struct _MInputMethodInfo MInputMethodInfo; + +struct _MInputMethodInfo +{ + MDatabase *mdb; + MSymbol language, name, extra; + MPlist *cmds, *configured_cmds, *bc_cmds; + MPlist *vars, *configured_vars, *bc_vars; + MText *description; + MText *title; + MPlist *maps; + MPlist *states; + MPlist *macros; + MPlist *externals; + unsigned long tick; +}; + +typedef struct MIMState MIMState; + +typedef struct MIMMap MIMMap; + +typedef struct MIMInputStack MIMInputStack; + +typedef struct +{ + /** The current state. */ + MIMState *state; + + /** The previous state. */ + MIMState *prev_state; + + /** The current map. */ + MIMMap *map; + + /** Table of typed keys. */ + int size, inc, used; + MSymbol *keys; + + /** Index of the key handled firstly in the current state. */ + int state_key_head; + + /** Index of the key not yet handled. */ + int key_head; + + /** Index of the key at the time of committing. */ + int commit_key_head; + + /** Saved M-text when entered in the current state. */ + MText *preedit_saved; + + /** The insertion position when shifted to the current state. */ + int state_pos; + + /** List of markers. */ + MPlist *markers; + + /** List of variables. */ + MPlist *vars; + + MPlist *vars_saved; + + MText *preceding_text, *following_text; + + int key_unhandled; + + /** Used by minput_win_driver (input-win.c). */ + void *win_info; + + MPlist *state_hook; + + unsigned long tick; + + /* A pushing/switching input method is recorded here by + take_action_list (). */ + MPlist *pushing_or_switching; + /* List of pointers to MInputContext for fallback input methods. */ + MPlist *fallbacks; + MIMInputStack *stack; +} MInputContextInfo; + +#define MINPUT_KEY_SHIFT_MODIFIER (1 << 0) +#define MINPUT_KEY_CONTROL_MODIFIER (1 << 1) +#define MINPUT_KEY_META_MODIFIER (1 << 2) +#define MINPUT_KEY_ALT_MODIFIER (1 << 3) +#define MINPUT_KEY_SUPER_MODIFIER (1 << 4) +#define MINPUT_KEY_HYPER_MODIFIER (1 << 5) +#define MINPUT_KEY_ALTGR_MODIFIER (1 << 6) + +extern MSymbol minput__char_to_key (int c); + +#endif /* not _M17N_INPUT_H_ */ diff --git a/src/internal-flt.h b/src/internal-flt.h new file mode 100644 index 0000000..17aecaf --- /dev/null +++ b/src/internal-flt.h @@ -0,0 +1,49 @@ +/* internal-flt.h -- common header file for the internal FLT API. + Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M_INTERNAL_FLT_H +#define _M_INTERNAL_FLT_H + +#define MAKE_COMBINING_CODE(base_y, base_x, add_y, add_x, off_y, off_x) \ + (((off_y) << 16) \ + | ((off_x) << 8) \ + | ((base_x) << 6) \ + | ((base_y) << 4) \ + | ((add_x) << 2) \ + | (add_y)) + +#define COMBINING_CODE_OFF_Y(code) ((((code) >> 16) & 0xFF) - 128) +#define COMBINING_CODE_OFF_X(code) ((((code) >> 8) & 0xFF) - 128) +#define COMBINING_CODE_BASE_X(code) (((code) >> 6) & 0x3) +#define COMBINING_CODE_BASE_Y(code) (((code) >> 4) & 0x3) +#define COMBINING_CODE_ADD_X(code) (((code) >> 2) & 0x3) +#define COMBINING_CODE_ADD_Y(code) ((code) & 0x3) + +#define PACK_OTF_TAG(TAG) \ + ((((TAG) & 0x7F000000) >> 3) \ + | (((TAG) & 0x7F0000) >> 2) \ + | (((TAG) & 0x7F00) >> 1) \ + | ((TAG) & 0x7F)) + +extern MSymbol Mcombining; + +#endif /* _M_INTERNAL_FLT_H */ diff --git a/src/internal-gui.h b/src/internal-gui.h new file mode 100644 index 0000000..558311d --- /dev/null +++ b/src/internal-gui.h @@ -0,0 +1,270 @@ +/* internal-gui.h -- common header file for the internal GUI API. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M_INTERNAL_GUI_H +#define _M_INTERNAL_GUI_H + +enum MDeviceType + { + MDEVICE_SUPPORT_OUTPUT = 1, + MDEVICE_SUPPORT_INPUT = 2 + }; + +typedef struct MRealizedFont MRealizedFont; +typedef struct MRealizedFace MRealizedFace; +typedef struct MRealizedFontset MRealizedFontset; +typedef struct MDeviceDriver MDeviceDriver; + +/** Information about a frame. */ + +struct MFrame +{ + M17NObject control; + + MSymbol foreground, background, videomode; + + MFont *font; + + /** The default face of the frame. */ + MFace *face; + + /** The default realized face of the frame. */ + MRealizedFace *rface; + + /** The default width of one-char space. It is a width of SPACE + character of the default face. */ + int space_width; + + int average_width; + + /** The default ascent and descent of a line. It is ascent and + descent of ASCII font of the default face. */ + int ascent, descent; + + /** Initialized to 0 and incremented on each modification of a face + on which one of the realized faces is based. */ + unsigned tick; + + /** Pointer to device dependent information associated with the + frame. */ + void *device; + + /** The following members are set by "device_open" function of a + device dependent library. */ + + /** Logical OR of enum MDeviceType. */ + int device_type; + + /** Resolution (dots per inch) of the device. */ + int dpi; + + /** Correction of functions to manipulate the device. */ + MDeviceDriver *driver; + + /** List of font drivers. */ + MPlist *font_driver_list; + + /** List of realized fonts. */ + MPlist *realized_font_list; + + /** List of realized faces. */ + MPlist *realized_face_list; + + /** List of realized fontsets. */ + MPlist *realized_fontset_list; +}; + +#define M_CHECK_WRITABLE(frame, err, ret) \ + do { \ + if (! ((frame)->device_type & MDEVICE_SUPPORT_OUTPUT)) \ + MERROR ((err), (ret)); \ + } while (0) + +#define M_CHECK_READABLE(frame, err, ret) \ + do { \ + if (! ((frame)->device_type & MDEVICE_SUPPORT_INPUT)) \ + MERROR ((err), (ret)); \ + } while (0) + +enum glyph_type + { + GLYPH_CHAR, + GLYPH_SPACE, + GLYPH_PAD, + GLYPH_BOX, + GLYPH_ANCHOR, + GLYPH_TYPE_MAX + }; + +enum glyph_category + { + GLYPH_CATEGORY_NORMAL, + GLYPH_CATEGORY_MODIFIER, + GLYPH_CATEGORY_FORMATTER + }; + +typedef struct +{ + MFLTGlyph g; + MRealizedFace *rface; + unsigned left_padding : 1; + unsigned right_padding : 1; + unsigned enabled : 1; + unsigned bidi_level : 6; + unsigned category : 2; + unsigned type : 3; + unsigned libotf_positioning_type; +} MGlyph; + +struct MGlyphString +{ + M17NObject head; + + MFrame *frame; + int tick; + + int size, inc, used; + MGlyph *glyphs; + int from, to; + short width, height, ascent, descent; + short physical_ascent, physical_descent, lbearing, rbearing; + short text_ascent, text_descent, line_ascent, line_descent; + int indent, width_limit; + + /* Copied for .anti_alias but never set if the frame's + depth is less than 8. */ + unsigned anti_alias : 1; + + MDrawControl control; + + struct MGlyphString *next, *top; +}; + +#define MGLYPH(idx) \ + (gstring->glyphs + ((idx) >= 0 ? (idx) : (gstring->used + (idx)))) + +#define GLYPH_INDEX(g) \ + ((g) - gstring->glyphs) + +#define INIT_GLYPH(g) \ + (memset (&(g), 0, sizeof (g))) + +#define APPEND_GLYPH(gstring, g) \ + MLIST_APPEND1 ((gstring), glyphs, (g), MERROR_DRAW) + +#define INSERT_GLYPH(gstring, at, g) \ + do { \ + MLIST_INSERT1 ((gstring), glyphs, (at), 1, MERROR_DRAW); \ + (gstring)->glyphs[at] = g; \ + } while (0) + +#define DELETE_GLYPH(gstring, at) \ + do { \ + MLIST_DELETE1 (gstring, glyphs, at, 1); \ + } while (0) + +#define REPLACE_GLYPHS(gstring, from, to, len) \ + do { \ + int newlen = (gstring)->used - (from); \ + int diff = newlen - (len); \ + \ + if (diff < 0) \ + MLIST_DELETE1 (gstring, glyphs, (to) + newlen, -diff); \ + else if (diff > 0) \ + MLIST_INSERT1 ((gstring), glyphs, (to) + (len), diff, MERROR_DRAW); \ + memmove ((gstring)->glyphs + to, (gstring)->glyphs + (from + diff), \ + (sizeof (MGlyph)) * newlen); \ + (gstring)->used -= newlen; \ + } while (0) + +typedef struct MGlyphString MGlyphString; + +typedef struct +{ + short x, y; +} MDrawPoint; + +struct MDeviceDriver +{ + void (*close) (MFrame *frame); + void *(*get_prop) (MFrame *frame, MSymbol key); + void (*realize_face) (MRealizedFace *rface); + void (*free_realized_face) (MRealizedFace *rface); + void (*fill_space) (MFrame *frame, MDrawWindow win, + MRealizedFace *rface, int reverse, + int x, int y, int width, int height, + MDrawRegion region); + void (*draw_empty_boxes) (MDrawWindow win, int x, int y, + MGlyphString *gstring, + MGlyph *from, MGlyph *to, + int reverse, MDrawRegion region); + void (*draw_hline) (MFrame *frame, MDrawWindow win, + MGlyphString *gstring, + MRealizedFace *rface, int reverse, + int x, int y, int width, MDrawRegion region); + void (*draw_box) (MFrame *frame, MDrawWindow win, + MGlyphString *gstring, + MGlyph *g, int x, int y, int width, + MDrawRegion region); + + void (*draw_points) (MFrame *frame, MDrawWindow win, + MRealizedFace *rface, + int intensity, MDrawPoint *points, int num, + MDrawRegion region); + MDrawRegion (*region_from_rect) (MDrawMetric *rect); + void (*union_rect_with_region) (MDrawRegion region, MDrawMetric *rect); + void (*intersect_region) (MDrawRegion region1, MDrawRegion region2); + void (*region_add_rect) (MDrawRegion region, MDrawMetric *rect); + void (*region_to_rect) (MDrawRegion region, MDrawMetric *rect); + void (*free_region) (MDrawRegion region); + void (*dump_region) (MDrawRegion region); + MDrawWindow (*create_window) (MFrame *frame, MDrawWindow parent); + void (*destroy_window) (MFrame *frame, MDrawWindow win); + void (*map_window) (MFrame *frame, MDrawWindow win); + void (*unmap_window) (MFrame *frame, MDrawWindow win); + void (*window_geometry) (MFrame *frame, MDrawWindow win, + MDrawWindow parent, MDrawMetric *geometry); + void (*adjust_window) (MFrame *frame, MDrawWindow win, + MDrawMetric *current, MDrawMetric *new); + MSymbol (*parse_event) (MFrame *frame, void *arg, int *modifiers); +}; + +extern MSymbol Mlatin; + +extern MSymbol Mgd; + +extern int mfont__init (); +extern void mfont__fini (); + +extern int mface__init (); +extern void mface__fini (); + +extern int mdraw__init (); +extern void mdraw__fini (); + +extern int mfont__fontset_init (); +extern void mfont__fontset_fini (); + +extern int minput__win_init (); +extern void minput__win_fini (); + +#endif /* _M_INTERNAL_GUI_H */ diff --git a/src/internal.h b/src/internal.h new file mode 100644 index 0000000..c4a8431 --- /dev/null +++ b/src/internal.h @@ -0,0 +1,685 @@ +/* internal.h -- common header file for the internal CORE and SHELL APIs. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_INTERNAL_H_ +#define _M17N_INTERNAL_H_ + +/** @file internal.h + @brief a documentation for internal.h + + longer version of internal.h description +*/ + +extern int m17n__core_initialized; +extern int m17n__shell_initialized; +extern int m17n__gui_initialized; + +extern int mdebug_hook (); + +#if ENABLE_NLS +#include +#define _(String) dgettext ("m17n-lib", String) +#else +#define _(String) (String) +#endif + +/** Return with code RET while setting merror_code to ERR. */ + +#define MERROR(err, ret) \ + do { \ + merror_code = (err); \ + mdebug_hook (); \ + return (ret); \ + } while (0) + + +#define MERROR_GOTO(err, label) \ + do { \ + if ((err)) \ + merror_code = (err); \ + mdebug_hook (); \ + goto label; \ + } while (0) + + +#define MWARNING(err) \ + do { \ + mdebug_hook (); \ + goto warning; \ + } while (0) + +#define MFATAL(err) \ + do { \ + mdebug_hook (); \ + exit (err); \ + } while (0) + +#define MFAILP(cond) ((cond) ? 0 : mdebug_hook ()) + +#define M_CHECK_CHAR(c, ret) \ + if ((c) < 0 || (c) > MCHAR_MAX) \ + MERROR (MERROR_CHAR, (ret)); \ + else + + +/** Memory allocation stuffs. */ + +/* Call a handler function for memory full situation with argument + ERR. ERR must be one of enum MErrorCode. By default, the + handler function just calls exit () with argument ERR. */ + +#define MEMORY_FULL(err) \ + do { \ + (*m17n_memory_full_handler) (err); \ + exit (err); \ + } while (0) + + +/** The macro MTABLE_MALLOC () allocates memory (by malloc) for an + array of SIZE objects. The size of each object is determined by + the type of P. Then, it sets P to the allocated memory. ERR must + be one of enum MErrorCode. If the allocation fails, the macro + MEMORY_FULL () is called with argument ERR. */ + +#define MTABLE_MALLOC(p, size, err) \ + do { \ + if (! ((p) = (void *) malloc (sizeof (*(p)) * (size)))) \ + MEMORY_FULL (err); \ + } while (0) + + +/** The macro MTABLE_CALLOC() is like the macro MTABLE_MALLOC but use + calloc instead of malloc, thus the allocated memory are zero + cleared. */ + +#define MTABLE_CALLOC(p, size, err) \ + do { \ + if (! ((p) = (void *) calloc (sizeof (*(p)), size))) \ + MEMORY_FULL (err); \ + } while (0) + +#define MTABLE_CALLOC_SAFE(p, size) \ + ((p) = (void *) calloc (sizeof (*(p)), (size))) + + +/** The macro MTABLE_REALLOC () changes the size of memory block + pointed to by P to a size suitable for an array of SIZE objects. + The size of each object is determined by the type of P. ERR must + be one of enum MErrorCode. If the allocation fails, the macro + MEMORY_FULL () is called with argument ERR. */ + +#define MTABLE_REALLOC(p, size, err) \ + do { \ + if (! ((p) = (void *) realloc ((p), sizeof (*(p)) * (size)))) \ + MEMORY_FULL (err); \ + } while (0) + + +/** The macro MTABLE_ALLOCA () allocates memory (by alloca) for an + array of SIZE objects. The size of each object is determined by + the type of P. Then, it sets P to the allocated memory. ERR must + be one of enum MErrorCode. If the allocation fails, the macro + MEMORY_FULL () is called with argument ERR. */ + +#define MTABLE_ALLOCA(p, size, err) \ + do { \ + int allocasize = sizeof (*(p)) * (size); \ + if (! ((p) = (void *) alloca (allocasize))) \ + MEMORY_FULL (err); \ + memset ((p), 0, allocasize); \ + } while (0) + + +/** short description of MSTRUCT_MALLOC */ +/** The macro MSTRUCT_MALLOC () allocates memory (by malloc) for an + object whose size is determined by the type of P, and sets P to + the allocated memory. ERR must be one of enum MErrorCode. If + the allocation fails, the macro MEMORY_FULL () is called with + argument ERR. */ + +#define MSTRUCT_MALLOC(p, err) \ + do { \ + if (! ((p) = (void *) malloc (sizeof (*(p))))) \ + MEMORY_FULL (err); \ + } while (0) + + +#define MSTRUCT_CALLOC(p, err) MTABLE_CALLOC ((p), 1, (err)) + +#define MSTRUCT_CALLOC_SAFE(p) MTABLE_CALLOC_SAFE ((p), 1) + +#define USE_SAFE_ALLOCA \ + int sa_must_free = 0, sa_size = 0 + +/* P must be the same in all calls to SAFE_ALLOCA and SAFE_FREE in a + function. */ + +#define SAFE_ALLOCA(P, SIZE) \ + do { \ + if (sa_size < (SIZE)) \ + { \ + if (sa_must_free) \ + (P) = realloc ((P), (SIZE)); \ + else \ + { \ + (P) = alloca ((SIZE)); \ + if (! (P)) \ + { \ + (P) = malloc (SIZE); \ + sa_must_free = 1; \ + } \ + } \ + if (! (P)) \ + MEMORY_FULL (1); \ + sa_size = (SIZE); \ + } \ + } while (0) + +#define SAFE_FREE(P) \ + do { \ + if (sa_must_free && sa_size > 0) \ + { \ + free ((P)); \ + sa_must_free = sa_size = 0; \ + } \ + } while (0) + + +/** Extendable array. */ + +#define MLIST_RESET(list) \ + ((list)->used = 0) + + +#define MLIST_INIT1(list, mem, increment) \ + do { \ + (list)->size = (list)->used = 0; \ + (list)->inc = (increment); \ + (list)->mem = NULL; \ + } while (0) + + +#define MLIST_APPEND1(list, mem, elt, err) \ + do { \ + if ((list)->inc <= 0) \ + mdebug_hook (); \ + if ((list)->size == (list)->used) \ + { \ + (list)->size += (list)->inc; \ + MTABLE_REALLOC ((list)->mem, (list)->size, (err)); \ + } \ + (list)->mem[(list)->used++] = (elt); \ + } while (0) + + +#define MLIST_PREPEND1(list, mem, elt, err) \ + do { \ + if ((list)->inc <= 0) \ + mdebug_hook (); \ + if ((list)->size == (list)->used) \ + { \ + (list)->size += (list)->inc; \ + MTABLE_REALLOC ((list)->mem, (list)->size, (err)); \ + } \ + memmove ((list)->mem + 1, (list)->mem, \ + sizeof *((list)->mem) * ((list)->used)); \ + (list)->mem[0] = (elt); \ + (list)->used++; \ + } while (0) + + +#define MLIST_INSERT1(list, mem, idx, len, err) \ + do { \ + while ((list)->used + (len) > (list)->size) \ + { \ + (list)->size += (list)->inc; \ + MTABLE_REALLOC ((list)->mem, (list)->size, (err)); \ + } \ + memmove ((list)->mem + ((idx) + (len)), (list)->mem + (idx), \ + (sizeof *((list)->mem)) * ((list)->used - (idx))); \ + (list)->used += (len); \ + } while (0) + + +#define MLIST_DELETE1(list, mem, idx, len) \ + do { \ + memmove ((list)->mem + (idx), (list)->mem + (idx) + (len), \ + (sizeof *((list)->mem)) * ((list)->used - (idx) - (len))); \ + (list)->used -= (len); \ + } while (0) + + +#define MLIST_COPY1(list0, list1, mem, err) \ + do { \ + (list0)->size = (list0)->used = (list1)->used; \ + (list0)->inc = 1; \ + MTABLE_MALLOC ((list0)->mem, (list0)->used, (err)); \ + memcpy ((list0)->mem, (list1)->mem, \ + (sizeof (list0)->mem) * (list0)->used); \ + } while (0) + + +#define MLIST_FREE1(list, mem) \ + if ((list)->size) \ + { \ + free ((list)->mem); \ + (list)->mem = NULL; \ + (list)->size = (list)->used = 0; \ + } \ + else + + + +typedef struct +{ + void (*freer) (void *); + int size, inc, used; + unsigned *counts; +} M17NObjectRecord; + +typedef struct +{ + /**en Reference count of the object. */ + /**ja ���֥������Ȥλ��ȿ�. */ + unsigned ref_count : 16; + + unsigned ref_count_extended : 1; + + /**en A flag bit used for various perpose. */ + /**ja ���ޤ��ޤ���Ū���Ѥ�����ե饰�ӥå�. */ + unsigned flag : 15; + + union { + /**en If is zero, a function to free the + object. */ + /**ja �� 0 �ʤ�Х��֥������Ȥ��������ؿ�. */ + void (*freer) (void *); + /**en If is nonzero, a pointer to the + struct M17NObjectRecord. */ + /**ja �� 0 �Ǥʤ���й�¤�� M17NObjectRecord �ؤΥݥ���. */ + M17NObjectRecord *record; + } u; +} M17NObject; + + +/** Allocate a managed object OBJECT which has freer FREE_FUNC. */ + +#define M17N_OBJECT(object, free_func, err) \ + do { \ + MSTRUCT_CALLOC ((object), (err)); \ + ((M17NObject *) (object))->ref_count = 1; \ + ((M17NObject *) (object))->u.freer = free_func; \ + } while (0) + + +/**en Increment the reference count of OBJECT if the count is not + 0. */ +/**ja OBJECT �λ��ȿ��� 0 �Ǥʤ���� 1 ���䤹. */ + +#define M17N_OBJECT_REF(object) \ + do { \ + if (((M17NObject *) (object))->ref_count_extended) \ + m17n_object_ref (object); \ + else if (((M17NObject *) (object))->ref_count > 0) \ + { \ + ((M17NObject *) (object))->ref_count++; \ + if (! ((M17NObject *) (object))->ref_count) \ + { \ + ((M17NObject *) (object))->ref_count--; \ + m17n_object_ref (object); \ + } \ + } \ + } while (0) + + +#define M17N_OBJECT_REF_NTIMES(object, n) \ + do { \ + int i; \ + \ + if (((M17NObject *) (object))->ref_count_extended) \ + for (i = 0; i < n; i++) \ + m17n_object_ref (object); \ + else if (((M17NObject *) (object))->ref_count > 0) \ + { \ + int orig_ref_count = ((M17NObject *) (object))->ref_count; \ + \ + for (i = 0; i < n; i++) \ + if (! ++((M17NObject *) (object))->ref_count) \ + { \ + ((M17NObject *) (object))->ref_count = orig_ref_count; \ + for (i = 0; i < n; i++) \ + m17n_object_ref (object); \ + } \ + } \ + } while (0) + + +/**en Decrement the reference count of OBJECT if the count is greater + than 0. In that case, if the count becomes 0, free OBJECT. */ +/**ja OBJECT �λ��ȿ��� 0 ����礭����� 1 ���餹�����餷�� 0 �ˤʤ�� + OBJECT ���������. */ + +#define M17N_OBJECT_UNREF(object) \ + do { \ + if (object) \ + { \ + if (((M17NObject *) (object))->ref_count_extended \ + || mdebug__flags[MDEBUG_FINI]) \ + { \ + if (m17n_object_unref (object) == 0) \ + (object) = NULL; \ + } \ + else if (((M17NObject *) (object))->ref_count == 0) \ + break; \ + else \ + { \ + ((M17NObject *) (object))->ref_count--; \ + if (((M17NObject *) (object))->ref_count == 0) \ + { \ + if (((M17NObject *) (object))->u.freer) \ + (((M17NObject *) (object))->u.freer) (object); \ + else \ + free (object); \ + (object) = NULL; \ + } \ + } \ + } \ + } while (0) + +typedef struct _M17NObjectArray M17NObjectArray; + +struct _M17NObjectArray +{ + char *name; + int count; + int size, inc, used; + void **objects; + M17NObjectArray *next; +}; + +extern void mdebug__add_object_array (M17NObjectArray *array, char *name); + +#define M17N_OBJECT_ADD_ARRAY(array, name) \ + if (mdebug__flags[MDEBUG_FINI]) \ + mdebug__add_object_array (&array, name); \ + else + +extern void mdebug__register_object (M17NObjectArray *array, void *object); + +#define M17N_OBJECT_REGISTER(array, object) \ + if (mdebug__flags[MDEBUG_FINI]) \ + mdebug__register_object (&array, object); \ + else + +extern void mdebug__unregister_object (M17NObjectArray *array, void *object); + +#define M17N_OBJECT_UNREGISTER(array, object) \ + if (mdebug__flags[MDEBUG_FINI]) \ + mdebug__unregister_object (&array, object); \ + else + + + +struct MTextPlist; + +enum MTextCoverage + { + MTEXT_COVERAGE_ASCII, + MTEXT_COVERAGE_UNICODE, + MTEXT_COVERAGE_FULL + }; + +struct MText +{ + M17NObject control; + + unsigned format : 16; + unsigned coverage : 16; + + /**en Number of characters in the M-text */ + /**ja M-text ���ʸ���� */ + int nchars; + + /**en Number of bytes used to represent the characters in the M-text. */ + /**ja M-text ���ʸ����ɽ�魯������Ѥ�����Х��ȿ� */ + int nbytes; + + /**en Character sequence of the M-text. */ + /**ja M-text ���ʸ���� */ + unsigned char *data; + + /**en Number of bytes allocated for the @c data member. */ + /**ja ���� @c data �˳�����Ƥ�줿�Х��ȿ� */ + int allocated; + + /**en Pointer to the property list of the M-text. */ + /**ja M-text �Υץ��ѥƥ��ꥹ�ȤؤΥݥ��� */ + struct MTextPlist *plist; + + /**en Caches of the character position and the corresponding byte position. */ + /**ja ʸ�����֤�����б�����Х��Ȱ��֤Υ���å��� */ + int cache_char_pos, cache_byte_pos; +}; + +/** short description of M_CHECK_POS */ +/** longer description of M_CHECK_POS */ + +#define M_CHECK_POS(mt, pos, ret) \ + do { \ + if ((pos) < 0 || (pos) >= (mt)->nchars) \ + MERROR (MERROR_RANGE, (ret)); \ + } while (0) + + +/** short description of M_CHECK_POS_X */ +/** longer description of M_CHECK_POS_X */ + +#define M_CHECK_POS_X(mt, pos, ret) \ + do { \ + if ((pos) < 0 || (pos) > (mt)->nchars) \ + MERROR (MERROR_RANGE, (ret)); \ + } while (0) + + +/** short description of M_CHECK_RANGE */ +/** longer description of M_CHECK_RANGE */ + +#define M_CHECK_RANGE(mt, from, to, ret, ret2) \ + do { \ + if ((from) < 0 || (to) < (from) || (to) > (mt)->nchars) \ + MERROR (MERROR_RANGE, (ret)); \ + if ((from) == (to)) \ + return (ret2); \ + } while (0) + +#define M_CHECK_RANGE_X(mt, from, to, ret) \ + do { \ + if ((from) < 0 || (to) < (from) || (to) > (mt)->nchars) \ + MERROR (MERROR_RANGE, (ret)); \ + } while (0) + + +#define M_CHECK_POS_NCHARS(mt, pos, nchars, ret, ret2) \ + do { \ + int to = (pos) + (nchars); \ + \ + M_CHECK_RANGE ((mt), (pos), (to), (ret), (ret2)); \ + } while (0) + + +#define MTEXT_READ_ONLY_P(mt) ((mt)->allocated < 0) + +#define M_CHECK_READONLY(mt, ret) \ + do { \ + if ((mt)->allocated < 0) \ + MERROR (MERROR_MTEXT, (ret)); \ + } while (0) + +#define mtext_nchars(mt) ((mt)->nchars) + +#define mtext_nbytes(mt) ((mt)->nbytes) + +#define mtext_allocated(mt) ((mt)->allocated) + +#define mtext_reset(mt) (mtext_del ((mt), 0, (mt)->nchars)) + + + +enum MDebugFlag + { + MDEBUG_INIT, + MDEBUG_FINI, + MDEBUG_CHARSET, + MDEBUG_CODING, + MDEBUG_DATABASE, + MDEBUG_FONT, + MDEBUG_FLT, + MDEBUG_FONTSET, + MDEBUG_INPUT, + MDEBUG_ALL, + MDEBUG_MAX = MDEBUG_ALL + }; + +extern int mdebug__flags[MDEBUG_MAX]; +extern FILE *mdebug__output; +extern void mdebug__push_time (); +extern void mdebug__pop_time (); +extern void mdebug__print_time (); + +#define MDEBUG_FLAG() mdebug__flags[mdebug_flag] + +#define MDEBUG_PRINT0(FPRINTF) \ + do { \ + if (MDEBUG_FLAG ()) \ + { \ + FPRINTF; \ + fflush (mdebug__output); \ + } \ + } while (0) + +#define MDEBUG_PRINT(msg) \ + MDEBUG_PRINT0 (fprintf (mdebug__output, "%s", (msg))) + +#define MDEBUG_PRINT1(fmt, arg) \ + MDEBUG_PRINT0 (fprintf (mdebug__output, (fmt), (arg))) + +#define MDEBUG_PRINT2(fmt, arg1, arg2) \ + MDEBUG_PRINT0 (fprintf (mdebug__output, (fmt), (arg1), (arg2))) + +#define MDEBUG_PRINT3(fmt, arg1, arg2, arg3) \ + MDEBUG_PRINT0 (fprintf (mdebug__output, (fmt), (arg1), (arg2), (arg3))) + +#define MDEBUG_PRINT4(fmt, arg1, arg2, arg3, arg4) \ + MDEBUG_PRINT0 (fprintf (mdebug__output, (fmt), (arg1), (arg2), (arg3), (arg4))) + +#define MDEBUG_PRINT5(fmt, arg1, arg2, arg3, arg4, arg5) \ + MDEBUG_PRINT0 (fprintf (mdebug__output, (fmt), (arg1), (arg2), (arg3), (arg4), (arg5))) + +#define MDEBUG_DUMP(prefix, postfix, call) \ + do { \ + if (MDEBUG_FLAG ()) \ + { \ + fprintf (mdebug__output, "%s", prefix); \ + call; \ + fprintf (mdebug__output, "%s", postfix); \ + fflush (mdebug__output); \ + } \ + } while (0) + +#define MDEBUG_PUSH_TIME() \ + do { \ + if (MDEBUG_FLAG ()) \ + mdebug__push_time (); \ + } while (0) + + +#define MDEBUG_POP_TIME() \ + do { \ + if (MDEBUG_FLAG ()) \ + mdebug__pop_time (); \ + } while (0) + + +#define MDEBUG_PRINT_TIME(tag, ARG_LIST) \ + do { \ + if (MDEBUG_FLAG ()) \ + { \ + fprintf (mdebug__output, " [%s] ", tag); \ + mdebug__print_time (); \ + fprintf ARG_LIST; \ + fprintf (mdebug__output, "\n"); \ + } \ + } while (0) + + +#define SWAP_16(c) (((c) >> 8) | (((c) & 0xFF) << 8)) + +#define SWAP_32(c) \ + (((c) >> 24) | (((c) >> 8) & 0xFF00) \ + | (((c) & 0xFF00) << 8) | (((c) & 0xFF) << 24)) + + +/* Initialize/finalize function. */ + +extern int msymbol__init (); +extern void msymbol__fini (); + +extern int mplist__init (); +extern void mplist__fini (); + +extern int mtext__init (); +extern void mtext__fini (); + +extern int mtext__prop_init (); +extern void mtext__prop_fini (); + +extern int mchartable__init (); +extern void mchartable__fini (); + +extern int mcharset__init (); +extern void mcharset__fini (); + +extern int mcoding__init (); +extern void mcoding__fini (); + +extern int mdatabase__init (void); +extern void mdatabase__fini (void); + +extern int mchar__init (); +extern void mchar__fini (); + +extern int mlang__init (); +extern void mlang__fini (); + +extern int mlocale__init (); +extern void mlocale__fini (); + +extern int minput__init (); +extern void minput__fini (); + +#endif /* _M17N_INTERNAL_H_ */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/language.c b/src/language.c new file mode 100644 index 0000000..3316a33 --- /dev/null +++ b/src/language.c @@ -0,0 +1,839 @@ +/* language.c -- language (and script) module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#include +#include +#include +#include +#include +#include "m17n.h" +#include "m17n-misc.h" +#include "internal.h" +#include "language.h" +#include "symbol.h" +#include "plist.h" +#include "mtext.h" + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) + +static MPlist *language_list; +static MPlist *script_list; +static MPlist *langname_list; + +static MPlist * +load_lang_script_list (MSymbol tag0, MSymbol tag1, MSymbol tag2, MSymbol tag3) +{ + MDatabase *mdb = mdatabase_find (tag0, tag1, tag2, tag3); + MPlist *plist, *pl, *p; + + if (! mdb + || ! (plist = mdatabase_load (mdb))) + return NULL; + /* Check at least if the plist is ((SYMBOL ...) ...). */ + for (pl = plist; ! MPLIST_TAIL_P (pl);) + { + if (! MPLIST_PLIST_P (pl)) + mplist__pop_unref (pl); + else + { + p = MPLIST_PLIST (pl); + if (! MPLIST_SYMBOL_P (p)) + mplist__pop_unref (pl); + else + pl = MPLIST_NEXT (pl); + } + } + return plist; +} + +static int +init_language_list (void) +{ + language_list = load_lang_script_list (msymbol ("standard"), Mlanguage, + msymbol ("iso639"), Mnil); + if (! language_list) + { + language_list = mplist (); + MERROR (MERROR_DB, -1); + } + return 0; +} + + +static int +init_script_list (void) +{ + script_list = load_lang_script_list (msymbol ("standard"), Mscript, + msymbol ("unicode"), Mnil); + if (! script_list) + { + script_list = mplist (); + MERROR (MERROR_DB, -1); + } + return 0; +} + +static MPlist * +load_lang_name (MSymbol target3, MSymbol target2) +{ + MPlist *plist, *pl, *p; + + plist = mplist (); + mplist_add (plist, Msymbol, target3); + pl = mdatabase_list (Mlanguage, Mname, target3, Mnil); + if (! pl && target2 != Mnil) + pl = mdatabase_list (Mlanguage, Mname, target2, Mnil); + if (pl) + { + MPLIST_DO (p, pl) + { + MDatabase *mdb = MPLIST_VAL (p); + MPlist *p0 = mdatabase_load (mdb), *p1, *territories; + MSymbol script = mdatabase_tag (mdb)[3]; + + if (MPLIST_PLIST_P (p0)) + { + p1 = MPLIST_PLIST (p0); + if (MPLIST_SYMBOL_P (p1) && MPLIST_SYMBOL (p1) == Mlanguage) + { + p1 = MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (MPLIST_NEXT (p1)))); + territories = p1; + while (! MPLIST_TAIL_P (p1)) + { + if (MPLIST_SYMBOL_P (p1)) + p1 = MPLIST_NEXT (p1); + else + mplist__pop_unref (p1); + } + M17N_OBJECT_REF (territories); + mplist__pop_unref (p0); + } + else + territories = mplist (); + mplist_push (p0, Mplist, territories); + M17N_OBJECT_UNREF (territories); + mplist_push (p0, Msymbol, script); + mplist_add (plist, Mplist, p0); + M17N_OBJECT_UNREF (p0); + } + } + M17N_OBJECT_UNREF (pl); + } + mplist_push (langname_list, Mplist, plist); + M17N_OBJECT_UNREF (plist); + return plist; +} + + +/* Internal API */ + +int +mlang__init () +{ + msymbol_put_func (Mlanguage, Mtext_prop_serializer, + M17N_FUNC (msymbol__serializer)); + msymbol_put_func (Mlanguage, Mtext_prop_deserializer, + M17N_FUNC (msymbol__deserializer)); + Miso639_2 = msymbol ("iso639-2"); + Miso639_1 = msymbol ("iso639-1"); + + language_list = script_list = langname_list = NULL; + return 0; +} + +void +mlang__fini (void) +{ + M17N_OBJECT_UNREF (language_list); + M17N_OBJECT_UNREF (script_list); + M17N_OBJECT_UNREF (langname_list); +} + +/*=*/ + +/***en + @brief Get information about a language. + + The mlanguage_info () function returns a well-formed @e plist that + contains information about $LANGUAGE. $LANGUAGE is a symbol whose + name is an ISO639-2 3-letter language code, an ISO639-1 2-letter + language codes, or an English word. + + The format of the plist is: + +@verbatim + (ISO639-2 [ISO639-1 | nil] ENGLISH-NAME ["NATIVE-NAME" | nil] + ["REPRESENTATIVE-CHARACTERS"]) +@endverbatim + + where, ISO639-2 is a symbol whose name is 3-letter language code + of ISO639-2, ISO639-1 is a symbol whose name is 2-letter language + code of ISO639-1, ENGLISH-NAME is a symbol whose name is the + English name of the language, "NATIVE-NAME" is an M-text written + by the most natural way in the language, + "REPRESENTATIVE-CHARACTERS" is an M-text that contains + representative characters used by the language. + + It is assured that the formats of both M-texts are + #MTEXT_FORMAT_UTF_8. + + @return + If the information is available, this function returns a plist + that should not be modified nor freed. Otherwise, it returns + @c NULL. + + @seealso + mlanguage_list () */ + +MPlist * +mlanguage__info (MSymbol language) +{ + MPlist *plist; + + if (! language_list + && init_language_list () < 0) + return NULL; + + MPLIST_DO (plist, language_list) + { + MPlist *pl = MPLIST_PLIST (plist); + + if (MPLIST_SYMBOL (pl) == language) + return pl; + if (MPLIST_TAIL_P (pl)) + continue; + pl = MPLIST_NEXT (pl); + if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == language) + return MPLIST_PLIST (plist); + if (MPLIST_TAIL_P (pl)) + continue; + pl = MPLIST_NEXT (pl); + if (MPLIST_MTEXT_P (pl)) + { + MText *mt = MPLIST_MTEXT (pl); + + if (mtext_nbytes (mt) == MSYMBOL_NAMELEN (language) + && strncasecmp ((char *) MTEXT_DATA (MPLIST_MTEXT (pl)), + MSYMBOL_NAME (language), + MSYMBOL_NAMELEN (language)) == 0) + return MPLIST_PLIST (plist); + } + } + return NULL; +} + +static MPlist * +mscript__info (MSymbol script) +{ + MPlist *plist; + + if (! script_list + && init_script_list () < 0) + return NULL; + MPLIST_DO (plist, script_list) + { + MPlist *pl = MPLIST_PLIST (plist); + + if (MPLIST_SYMBOL (pl) == script) + return pl; + } + return NULL; +} + +MPlist * +mscript__char_list (MSymbol name) +{ + MPlist *plist = mscript__info (name); + + if (plist /* script name */ + && (plist = MPLIST_NEXT (plist)) /* language list */ + && ! MPLIST_TAIL_P (plist) + && (plist = MPLIST_NEXT (plist)) /* char list */ + && MPLIST_PLIST_P (plist)) + return MPLIST_PLIST (plist); + return NULL; +} + +MSymbol +mscript__otf_tag (MSymbol script) +{ + MPlist *plist = mscript__info (script); + + if (plist /* script name */ + && (plist = MPLIST_NEXT (plist)) /* language list */ + && ! MPLIST_TAIL_P (plist) + && (plist = MPLIST_NEXT (plist)) /* char list */ + && ! MPLIST_TAIL_P (plist) + && (plist = MPLIST_NEXT (plist)) /* otf tag */ + && MPLIST_SYMBOL_P (plist)) + return MPLIST_SYMBOL (plist); + return NULL; +} + +MSymbol +mscript__from_otf_tag (MSymbol otf_tag) +{ + MPlist *plist; + /* As it is expected that this function is called in a sequence with + the same argument, we use a cache. */ + static MSymbol last_otf_tag, script; + + if (! script_list) + { + last_otf_tag = script = Mnil; + if (init_script_list () < 0) + return Mnil; + } + if (otf_tag == last_otf_tag) + return script; + last_otf_tag = otf_tag; + script = Mnil; + MPLIST_DO (plist, script_list) + { + MPlist *pl = MPLIST_PLIST (plist), *p; + + if (pl /* script name */ + && (p = MPLIST_NEXT (pl)) /* language tag */ + && ! MPLIST_TAIL_P (p) + && (p = MPLIST_NEXT (p)) /* char list */ + && ! MPLIST_TAIL_P (p) + && (p = MPLIST_NEXT (p)) /* otf tag */ + && ! MPLIST_TAIL_P (p)) + { + if (MPLIST_SYMBOL_P (p)) + { + if (otf_tag == MPLIST_SYMBOL (p)) + return MPLIST_SYMBOL (pl); + } + else if (MPLIST_PLIST (p)) + { + MPlist *p0; + + MPLIST_DO (p0, MPLIST_PLIST (p)) + if (MPLIST_SYMBOL_P (p0) && otf_tag == MPLIST_SYMBOL (p0)) + return MPLIST_SYMBOL (pl); + } + } + } + return script; +} + +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/* External API */ + +MSymbol Miso639_1, Miso639_2; + +/*=*/ + +/***en + @brief List 3-letter language codes. + + The mlanguage_list () funciton returns a well-formed plist whose + keys are #Msymbol and values are symbols whose names are ISO639-2 + 3-letter language codes. + + @return + This function returns a plist. The caller should free it by + m17n_object_unref (). + + @seealso + mscript_list (). */ + +/***ja + @brief 3ʸ�����쥳���ɤ�ꥹ�Ȥ���. + + �ؿ� mlanguage_list () �ϡ������� (well-formed) plist ���֤����ƥ��� + �� #Msymbol �Ǥ��ꡢ�ġ����ͤ� ISO639-2 ������줿3ʸ�����쥳�� + �ɤ�̾���Ȥ��륷��ܥ�Ǥ��롣 + + @return + ���δؿ����֤� plist �ϡ��ƤӽФ�¦�� m17n_object_unref () ��Ȥ� + �Ʋ�������ɬ�פ����롣 + + @seealso + mscript_list (). */ + +MPlist * +mlanguage_list (void) +{ + MPlist *plist, *pl, *p, *p0; + + if (! language_list + && init_language_list () < 0) + return NULL; + plist = pl = mplist (); + MPLIST_DO (p, language_list) + { + p0 = MPLIST_PLIST (p); + pl = mplist_add (pl, Msymbol, MPLIST_VAL (p0)); + } + return plist; +} + +/*=*/ + +/***en + @brief Get a language code. + + The mlanguage_code () function returns a symbol whose name is the + ISO639 language code of $LANGUAGE. $LANGUAGE is a symbol whose + name is an ISO639-2 3-letter language code, an ISO639-1 2-letter + language codes, or an English word. + + $LEN specifies the type of the returned language code. If it is + 3, an ISO639-2 3-letter language code is returned. If it is 2, an + ISO639-1 2-letter language code is returned when defined; + otherwise #Mnil is returned. If it is 0, a 2-letter code is + returned when defined; otherwise a 3-letter code is returned. + + @return + If the information is available, this function returns a non-#Mnil + symbol. Otherwise, it returns #Mnil. + + @seealso + mlanguage_name_list (), mlanguage_text (). */ + +/***ja + @brief ���쥳���ɤ�����. + + �ؿ� mlanguage_code () �ϡ�$LANGUAGE ���б����� ISO-639 ���쥳���� + ��̾���Ǥ���褦�ʥ���ܥ���֤���$LANGUAGE �ϥ���ܥ�Ǥ��ꡢ���� + ̾���ϡ�ISO639-2 3ʸ�����쥳���ɡ�ISO639-1 2ʸ�����쥳���ɡ��Ѹ�̾�� + �Τ����줫�Ǥ��롣 + + $LEN ���֤������쥳���ɤμ������ꤹ�롣$LEN ��3�ξ��� + ISO639-2 3ʸ�����쥳���ɤ��֤���롣2�ξ��ϡ��⤷�������Ƥ��� + �� ISO639-1 2ʸ�����쥳���ɤ��������Ǥʤ���� #Mnil ���֤���롣0 + �ξ��ϡ��⤷�������Ƥ����2ʸ�������ɤ��������Ǥʤ����3ʸ������ + �ɤ��֤���롣 + + @return + �⤷����������С����δؿ��� #Mnil �ʳ��Υ���ܥ���֤������� + �Ǥʤ���� #Mnil ���֤��� + + @seealso + mlanguage_name (), mlanguage_text (). */ + +MSymbol +mlanguage_code (MSymbol language, int len) +{ + MPlist *plist = mlanguage__info (language); + MSymbol code; + + if (! plist) + return Mnil; + if (! MPLIST_SYMBOL_P (plist)) + return Mnil; + code = MPLIST_SYMBOL (plist); + if (len == 3) + return code; + plist = MPLIST_NEXT (plist); + return ((MPLIST_SYMBOL_P (plist) && MPLIST_SYMBOL (plist) != Mnil) + ? MPLIST_SYMBOL (plist) + : len == 0 ? code : Mnil); +} + +/*=*/ + +/***en + @brief Return the language names written in the specified language. + + The mlanguage_name_list () function returns a plist of LANGUAGE's + names written in TARGET language. SCRIPT and TERRITORY, if not #Mnil, + specifies which script and territory to concern at first. + + LANGUAGE and TARGET must be a symbol whose name is an ISO639-2 + 3-letter language code or an ISO639-1 2-letter language codes. + TARGET may be #Mnil, in which case, the language of the current + locale is used. If locale is not set or is C, English is used. + + SCRIPT and TERRITORY must be a symbol whose name is a script and + territory name of a locale (e.g. "TW", "SG") respectively. + + @return + If the translation is available, this function returns a non-empty + plist. The first element has key #MText and the value is an + M-text of a translated language name. If the succeeding elements + also have key #MText, their values are M-texts of alternate + translations. + + If no translation is available, @c NULL is returned. + + The returned plist should not be modified nor freed. + + @seealso + mlanguage_code (), mlanguage_text (). */ + +MPlist * +mlanguage_name_list (MSymbol language, MSymbol target, + MSymbol script, MSymbol territory) +{ + MPlist *plist, *pl; + MSymbol language2, target2; + + plist = mlanguage__info (language); + if (! plist) + return NULL; + language = MPLIST_SYMBOL (plist); + language2 = MPLIST_SYMBOL (MPLIST_NEXT (plist)); + if (target != Mnil) + { + plist = mlanguage__info (target); + if (! plist) + return NULL; + target = MPLIST_SYMBOL (plist); + target2 = MPLIST_SYMBOL (MPLIST_NEXT (plist)); + } + else + { + MLocale *locale = mlocale_set (LC_MESSAGES, NULL); + + if (! locale) + { + target = msymbol ("eng"); + target2 = msymbol ("en"); + script = territory = Mnil; + } + else + { + target = mlocale_get_prop (locale, Mlanguage); + plist = mlanguage__info (target); + if (! plist) + return NULL; + target = MPLIST_SYMBOL (plist); + target2 = MPLIST_SYMBOL (MPLIST_NEXT (plist)); + script = mlocale_get_prop (locale, Mscript); + territory = mlocale_get_prop (locale, Mterritory); + } + } + + /* Now both LANGUAGE and TARGET are 3-letter codes. */ + if (! langname_list) + langname_list = mplist (); + plist = mplist__assq (langname_list, target); + if (plist) + plist = MPLIST_PLIST (plist); + else + plist = load_lang_name (target, target2); + + /* PLIST = (TARGET (SCRIPT (TERRITORY ...) (LANG-CODE NAME ...) ...) ...) */ + plist = MPLIST_NEXT (plist); + if (MPLIST_TAIL_P (plist)) + return NULL; + + MPLIST_DO (pl, plist) + { + MPlist *p = MPLIST_PLIST (pl), *p0; + + if (MPLIST_SYMBOL (p) == script + && (territory == Mnil + || mplist_find_by_value (MPLIST_PLIST (MPLIST_NEXT (p)), + territory)) + && (p = MPLIST_NEXT (MPLIST_NEXT (p))) + && ((p0 = mplist__assq (p, language)) + || (p0 = mplist__assq (p, language2)))) + { + plist = p0; + break; + } + } + if (MPLIST_TAIL_P (pl)) + { + MPLIST_DO (pl, plist) + { + MPlist *p = MPLIST_NEXT (MPLIST_PLIST (pl)), *p0; + + if ((territory == Mnil + || mplist_find_by_value (MPLIST_VAL (p), territory)) + && (p = MPLIST_NEXT (MPLIST_NEXT (p))) + && ((p0 = mplist__assq (p, language)) + || (p0 = mplist__assq (p, language2)))) + { + plist = p0; + break; + } + } + if (MPLIST_TAIL_P (pl)) + { + MPLIST_DO (pl, plist) + { + MPlist *p = MPLIST_NEXT (MPLIST_NEXT (MPLIST_PLIST (pl))), *p0; + + if ((p0 = mplist__assq (p, language)) + || (p0 = mplist__assq (p, language2))) + { + plist = p0; + break; + } + } + if (MPLIST_TAIL_P (pl)) + return NULL; + } + } + + plist = MPLIST_NEXT (MPLIST_PLIST (plist)); + if (territory != Mnil) + { + MPLIST_DO (pl, MPLIST_NEXT (plist)) + if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == territory) + break; + if (! MPLIST_TAIL_P (pl) + && (pl = MPLIST_NEXT (pl)) + && MPLIST_MTEXT_P (pl)) + return pl; + } + MPLIST_DO (plist, plist) + if (MPLIST_MTEXT_P (plist)) + break; + return (MPLIST_MTEXT_P (plist) ? plist : NULL); +} + +/*=*/ + +/***en + @brief Return the language name written in that language. + + The mlanguage_text () function returns, in the form of M-text, the + language name of $LANGUAGE written in $LANGUAGE. If the + representative characters of the language are known, the + characters of the returned M-text has a text property whose key is + #Mtext and whose value is an M-text that contains the + representative characters. + + @return + If the information is available, this function returns an M-text + that should not be modified nor freed. Otherwise, it returns @c + NULL. + + @seealso + mlanguage_code (), mlanguage_name (). */ + +/***ja + @brief Ϳ����줿���켫�Ȥǽ񤫤줿����̾���֤�. + + �ؿ� mlanguage_text () �ϡ����� $LANGUAGE �ǽ񤫤줿 $LANGUAGE �� + ̾���� M-text �η������֤������θ������ɽŪ��ʸ�����狼�äƤ���� + ��ϡ��֤���� M-text �γ�ʸ���ˡ������� #Mtext ���ͤ�������ɽŪ�� + ʸ����ޤ� M-text �Ǥ���褦�ʥƥ����ȥץ��ѥƥ����ղä���롣 + + @return + �����������줿��硢���δؿ����֤� M-text ���ѹ������������ + ���ꤷ�ƤϤ����ʤ������������ʤ��ä����� @c NULL ���֤���롣 + + @seealso + mlanguage_code (), mlanguage_name (). */ + +MText * +mlanguage_text (MSymbol language) +{ + MPlist *plist = mlanguage__info (language); + MText *mt; + + if (! plist) + return NULL; + plist = MPLIST_NEXT (plist); + if (MPLIST_TAIL_P (plist)) + return NULL; + plist = MPLIST_NEXT (plist); + if (MPLIST_TAIL_P (plist)) + return NULL; + plist = MPLIST_NEXT (plist); + if (! MPLIST_MTEXT_P (plist)) + return NULL; + mt = MPLIST_MTEXT (plist); + if (mtext_nchars (mt) == 0) + return NULL; + plist = MPLIST_NEXT (plist); + if (MPLIST_MTEXT_P (plist) + && ! mtext_get_prop (mt, 0, Mtext)) + mtext_put_prop (mt, 0, mtext_nchars (mt), Mtext, MPLIST_MTEXT (plist)); + return mt; +} + +/***en + @brief List script names. + + The mscript_list () funciton returns a well-formed plist whose + keys are #Msymbol and values are symbols whose names are script + names. + + @return + This function returns a plist. The caller should free it by + m17n_object_unref (). + + @seealso + mscript_language_list (), mlanguage_list (). */ + +/***ja + @brief ������ץ�̾��ꥹ�Ȥ���. + + �ؿ� mscript_list () �ϡ������� (well-formed) plist ���֤����ƥ��� + �� #Msymbol �Ǥ��ꡢ�ġ����ͤϥ�����ץ�̾��̾���Ȥ��륷��ܥ�Ǥ� + �롣 + + @return + ���δؿ����֤� plist �ϡ��ƤӽФ�¦�� m17n_object_unref () ��Ȥ� + �Ʋ�������ɬ�פ����롣 + + @seealso + mscript_language_list (), mlanguage_list (). */ + +MPlist * +mscript_list (void) +{ + MPlist *plist, *pl, *p, *p0; + + if (! script_list + && init_script_list () < 0) + return NULL; + plist = pl = mplist (); + MPLIST_DO (p, script_list) + { + p0 = MPLIST_PLIST (p); + pl = mplist_add (pl, Msymbol, MPLIST_VAL (p0)); + } + return plist; +} + +/*=*/ + +/***en + @brief List languages that use a specified script. + + The mscript_language_list () function lists languages that use + $SCRIPT. $SCRIPT is a symbol whose name is the lower-cased + version of a script name that appears in the Unicode Character + Database. + + @return + + This function returns a well-formed plist whose keys are #Msymbol + and values are symbols whose names are ISO639-1 2-letter codes (or + ISO639-2 3-letter codes, if the former is not available). The + caller should not modify nor free it. If the m17n library does + not know about $SCRIPT, it returns @ c NULL. + + @seealso + mscript_list (), mlanguage_list (). */ + +/***ja + @brief Ϳ����줿������ץȤ��Ѥ�������ꥹ�Ȥ���. + + �ؿ� mscript_language_list () �ϡ�$SCRIPT ���Ѥ�������ꥹ�Ȥ��롣 + $SCRIPT �ϥ���ܥ�ǡ�����̾���� Unicode Character Database �˼��� + ��Ƥ��륹����ץ�̾�򤹤٤ƾ�ʸ���ˤ�����ΤǤ��롣 + + @return + ���δؿ��ϡ������� (well-formed) plist ���֤����ƥ����� + #Msymbol �Ǥ��ꡢ�ġ����ͤ� ISO639-1 ������줿2ʸ�����쥳���� + (�������Ƥ��ʤ����� ISO639-2 ������줿3ʸ�����쥳����) ��̾ + ���Ȥ��륷��ܥ�Ǥ��롣�֤���� plist ���ѹ���������������ꤷ�� + �Ϥʤ�ʤ���$SCRIPT ��̤�Τξ��� @c NULL ���֤���롣 + + @seealso + mscript_list (), mlanguage_list (). */ + + +MPlist * +mscript_language_list (MSymbol script) +{ + MPlist *plist = mscript__info (script); + + if (plist /* script name */ + && (plist = MPLIST_NEXT (plist)) /* language list */ + && MPLIST_PLIST_P (plist)) + return MPLIST_PLIST (plist); + return NULL; +} + +/*** @} */ +/*=*/ +/***en + @name Obsolete functions +*/ +/***ja + @name Obsolete �ʴؿ� +*/ +/*** @{ */ + +/***en + @brief Get an English language name. + + This function is obsolete. Use mlanguage_name_list () instead. + + The mlanguage_name () function returns a symbol whose name is an + English name of $LANGUAGE. $LANGUAGE is a symbol whose name is an + ISO639-2 3-letter language code, an ISO639-1 2-letter language + codes, or an English word. + + @return + If the information is available, this function returns a non-#Mnil + symbol. Otherwise, it returns #Mnil. + + @seealso + mlanguage_code (), mlanguage_text (). */ + +/***ja + @brief ����αѸ�̾������. + + �ؿ� mlanguage_name () �ϡ�$LANGUAGE �αѸ�̾��̾���Ȥ���褦�ʥ� + ��ܥ���֤���$LANGUAGE �ϥ���ܥ�Ǥ��ꡢ����̾���ϡ�ISO639-2 3ʸ + �����쥳���ɡ�ISO639-1 2ʸ�����쥳���ɡ��Ѹ�̾���Τ����줫�Ǥ��롣 + + @return + ���Ƥ������������ʤ顢���δؿ��� #Mnil �ʳ��Υ���ܥ���� + ���������Ǥʤ���� #Mnil ���֤��� + + @seealso + mlanguage_code (), mlanguage_text (). */ + +MSymbol +mlanguage_name (MSymbol language) +{ + MPlist *plist = mlanguage__info (language); + MText *mt; + char *str; + + if (! plist) /* 3-letter code */ + return Mnil; + plist = MPLIST_NEXT (plist); /* 2-letter code */ + if (MPLIST_TAIL_P (plist)) + return Mnil; + plist = MPLIST_NEXT (plist); /* english name */ + if (! MPLIST_MTEXT_P (plist)) + return Mnil; + mt = MPLIST_MTEXT (plist); + str = alloca (mtext_nbytes (mt)); + memcpy (str, MTEXT_DATA (mt), mtext_nbytes (mt)); + str[0] = tolower (str[0]); + return msymbol__with_len (str, mtext_nbytes (mt)); +} + +/*=*/ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/language.h b/src/language.h new file mode 100644 index 0000000..665d0d9 --- /dev/null +++ b/src/language.h @@ -0,0 +1,32 @@ +/* language.h -- header file for the language (and script) module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_LANGUAGE_H_ +#define _M17N_LANGUAGE_H_ + +extern MPlist *mscript__char_list (MSymbol script); + +extern MSymbol mscript__otf_tag (MSymbol script); + +extern MSymbol mscript__from_otf_tag (MSymbol otf_tag); + +#endif /* _M17N_LANGUAGE_H_ */ diff --git a/src/linkcore.c b/src/linkcore.c new file mode 100644 index 0000000..90749ef --- /dev/null +++ b/src/linkcore.c @@ -0,0 +1,32 @@ +/* linkcore.c -- test program for linking with m17n-core.so. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + +This file is part of the m17n library. + +The m17n library 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. + +The m17n 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the m17n library; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + +#include +#include "m17n-core.h" + +int +main () +{ + M17N_INIT (); + M17N_FINI (); + exit (0); +} diff --git a/src/linkgui.c b/src/linkgui.c new file mode 100644 index 0000000..a7bb313 --- /dev/null +++ b/src/linkgui.c @@ -0,0 +1,33 @@ +/* linkgui.c -- test program for linking with m17n-X.so. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#include +#include "m17n-gui.h" +#include "m17n-misc.h" + +int +main () +{ + M17N_INIT (); + M17N_FINI (); + exit (0); +} diff --git a/src/linkshell.c b/src/linkshell.c new file mode 100644 index 0000000..fef7e25 --- /dev/null +++ b/src/linkshell.c @@ -0,0 +1,32 @@ +/* linkshell.c -- test program for linking with m17n.so. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#include +#include + +int +main () +{ + M17N_INIT (); + M17N_FINI (); + exit (0); +} diff --git a/src/locale.c b/src/locale.c new file mode 100644 index 0000000..5c20a58 --- /dev/null +++ b/src/locale.c @@ -0,0 +1,638 @@ +/* locale.c -- locale module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nLocale + @brief Locale objects and API for them. + + The m17n library represents locale related information as objects + of type #MLocale. */ + +/***ja + @addtogroup m17nLocale + @brief �������륪�֥������ȤȤ���˴ؤ��� API. + + m17n �饤�֥��ϥ��������Ϣ����� #MLocale ���Υ��֥������Ȥ�ɽ�����롣 */ + +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#ifdef HAVE_LANGINFO_H +#include +#endif +#include + +#include "m17n.h" +#include "m17n-misc.h" +#include "internal.h" +#include "symbol.h" +#include "coding.h" +#include "textprop.h" +#include "mlocale.h" + +static MSymbol M_locale; +static MSymbol M_xfrm; + + +/** Structure of locales. */ + +struct MLocale +{ + M17NObject control; + MSymbol name; + MSymbol language; + MSymbol territory; + MSymbol modifier; + MSymbol codeset; + MSymbol coding; +}; + + +/** The current locales of each category. */ +MLocale *mlocale__collate, *mlocale__ctype; +MLocale *mlocale__messages, *mlocale__time; + +/* These are currently not used. */ +#if 0 +MLocale *mlocale_monetary, *mlocale_numeric, ; +#endif + +/** Parse locale name NAME and return a newly created MLocale object. */ + +static MLocale * +make_locale (const char *name) +{ + char *str; + int len; + MLocale *locale; + char c; + + M17N_OBJECT (locale, NULL, MERROR_LOCALE); + locale->name = msymbol (name); + msymbol_put (locale->name, M_locale, (void *) locale); + M17N_OBJECT_UNREF (locale); + + len = strlen (name) + 1; + str = alloca (len); + memcpy (str, name, len); + + c = '\0'; + while (1) + { + char c1; + int i; + + for (i = 0; str[i]; i++) + if (str[i] == '_' || str[i] == '.' || str[i] == '@') + break; + c1 = str[i]; + str[i] = '\0'; + if (c == '\0') + /* The first field is for language. */ + locale->language = msymbol (str); + else if (c == '_') + /* The field following '_' is for territory. */ + locale->territory = msymbol (str); + else if (c == '.') + /* The field following '.' is for codeset. */ + locale->codeset = msymbol (str); + else + /* The other field is for modifier. */ + locale->modifier = msymbol (str); + if (! c1) + break; + c = c1; + str += i + 1; + } + +#ifdef HAVE_NL_LANGINFO +#ifdef CODESET + /* If we can use nl_langinfo () to retrieve a codeset name, respect + it over the codeset name extracted from the locale name. */ + locale->codeset = msymbol (nl_langinfo (CODESET)); +#endif +#endif + + /* If the locale name specifies a codeset, get the corresponding + coding system. */ + if (locale->codeset != Mnil) + { + locale->coding = mconv_resolve_coding (locale->codeset); + if (locale->coding == Mnil) + locale->coding = Mcoding_us_ascii; + } + else + locale->coding = Mcoding_us_ascii; + return locale; +} + + +/** Decode the byte sequence at BUF of length SIZE bytes by the coding + system associated with LOCALE, and return a generated M-text. */ + +static MText * +decode_locale (unsigned char *buf, int size, MLocale *locale) +{ + return mconv_decode_buffer (locale->coding, buf, size); +} + + +/** Encode the M-text MT by the coding system associated with LOCALE, + and store the resulting bytes in the memory area at BUF of *SIZE + bytes. If the area is too short, allocate a new and wider area. + Store the length of the generated bytes in the place pointed by + SIZE, and return the address of those bytes. */ + +static unsigned char * +encode_locale (MText *mt, unsigned char *buf, int *size, MLocale *locale) +{ + int nbytes = mconv_encode_buffer (locale->coding, mt, buf, *size - 1); + + if (nbytes < 0) + { + buf = NULL; + *size *= 2; + do { + MTABLE_REALLOC (buf, *size, MERROR_LOCALE); + nbytes = mconv_encode_buffer (mlocale__ctype->coding, mt, buf, + *size - 1); + } while (nbytes < 0); + } + buf[nbytes] = '\0'; + *size = nbytes; + return buf; +} + + +/** Structure of transformed strings. The function mtext_coll () + caches this object in an M-text as a text property. */ + +typedef struct { + /* Common header for a managed object. */ + M17NObject control; + + /* Locale corresponding to . */ + MLocale *locale; + + /** Result of strxfrm. */ + char *str; +} MXfrm; + + +static void +free_xfrm (void *object) +{ + MXfrm *xfrm = (MXfrm *) object; + + M17N_OBJECT_UNREF (xfrm->locale); + free (xfrm->str); +} + +static char * +get_xfrm (MText *mt) +{ + MTextProperty *prop = mtext_get_property (mt, 0, M_xfrm); + MXfrm *xfrm; + int size; + unsigned char *buf, *newbuf; + int request; + + if (prop) + { + if (prop->end == mt->nchars) + { + xfrm = (MXfrm *) prop->val; + if (xfrm->locale == mlocale__ctype) + return xfrm->str; + } + mtext_detach_property (prop); + } + + size = mt->nbytes; + buf = alloca (size); + newbuf = encode_locale (mt, buf, &size, mlocale__ctype); + M17N_OBJECT (xfrm, free_xfrm, MERROR_MTEXT); + xfrm->str = malloc (size); + request = strxfrm (xfrm->str, (char *) newbuf, size); + if (request >= size) + { + xfrm->str = realloc (xfrm->str, request); + strxfrm (xfrm->str, (char *) newbuf, size); + } + if (buf != newbuf) + free (newbuf); + prop = mtext_property (M_xfrm, xfrm, MTEXTPROP_VOLATILE_WEAK); + mtext_attach_property (mt, 0, mt->nchars, prop); + M17N_OBJECT_UNREF (prop); + return xfrm->str; +} + + +/* Internal API */ + +int +mlocale__init () +{ + M_locale = msymbol_as_managing_key (" locale"); + + Mterritory = msymbol ("territory"); + Mcodeset = msymbol ("codeset"); + + mlocale__collate = mlocale_set (LC_COLLATE, NULL); + M17N_OBJECT_REF (mlocale__collate); + mlocale__ctype = mlocale_set (LC_CTYPE, NULL); + M17N_OBJECT_REF (mlocale__ctype); + mlocale__messages = mlocale_set (LC_MESSAGES, NULL); + M17N_OBJECT_REF (mlocale__messages); + mlocale__time = mlocale_set (LC_TIME, NULL); + M17N_OBJECT_REF (mlocale__time); + + M_xfrm = msymbol_as_managing_key (" xfrm"); + return 0; +} + +void +mlocale__fini () +{ + M17N_OBJECT_UNREF (mlocale__collate); + M17N_OBJECT_UNREF (mlocale__ctype); + M17N_OBJECT_UNREF (mlocale__messages); + M17N_OBJECT_UNREF (mlocale__time); +} + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/* External API */ +/*** @addtogroup m17nLocale */ +/*** @{ */ + +/*=*/ +/***en The symbol whose name is "territory". */ +/***ja "territory" �Ȥ���̾������ĥ���ܥ�. */ +MSymbol Mterritory; + +/*=*/ +/***en The symbol whose name is "modifier". */ +/***ja "modifier" �Ȥ���̾������ĥ���ܥ�. */ +MSymbol Mmodifier; + +/*=*/ +/***en The symbol whose name is "codeset". */ +/***ja "codeset" �Ȥ���̾������ĥ���ܥ�. */ +MSymbol Mcodeset; + +/*=*/ + +/***en + @brief Set the current locale. + + The mlocale_set () function sets or query a part of the current + locale. The part is specified by $CATEGORY which must be a valid + first argument to setlocale (). + + If $LOCALE is not NULL, the locale of the specified part is set to + $LOCALE. If $LOCALE is not supported by the system, the current + locale is not changed. + + If $LOCALE is NULL, the current locale of the specified part is + queried. + + @return + If the call is successful, mlocale_set () returns an opaque locale + object that corresponds to the locale. The name of the locale can + be acquired by the function mlocale_get_prop (). + Otherwise, it returns NULL. */ + +/***ja + @brief ���ߤΥ�����������ꤹ��. + + �ؿ� mlocale_set () �ϸ��ߤΥ�������ΰ��������ꤷ�����䤤��碌���ꤹ�롣�����ǰ����Ȥ� + $CATEGORY �ǻ��ꤵ�졢setlocale () ��ͭ�����������Ȥʤ��ΤǤʤ��ƤϤʤ�ʤ��� + + $LOCALE �� NULL �Ǥʤ���С����ꤷ����ʬ�Υ������뤬$LOCALE �����ꤵ��롣 + $LOCALE �������ƥ�˥��ݡ��Ȥ���Ƥ��ʤ���С�����ϹԤ�줺�����ߤΥ���������Ѥ��ʤ��� + + $LOCALE �� NULL �ʤ�С����ߤΥ�������λ��ꤷ����ʬ���䤤��碌�롣 + + @return + + �ƤӽФ�����������С�mlocale_set () �ϥ���������б����� opaque + �������륪�֥������Ȥ��֤������������̾���ϴؿ� + mlocale_get_prop () �ˤ�ä����뤳�Ȥ��Ǥ��롣 + �����Ǥʤ���� NULL ���֤��� + */ + +/*** + @errors + @c MERROR_LOCALE */ + +MLocale * +mlocale_set (int category, const char *name) +{ + char *new; + MLocale *locale; + + new = setlocale (category, name); + if (! new) + return NULL; + + locale = (MLocale *) msymbol_get (msymbol (new), M_locale); + if (! locale) + locale = make_locale (new); + if (! locale) + return NULL; + if (name && (category == LC_ALL || category == LC_COLLATE)) + { + M17N_OBJECT_REF (locale); + M17N_OBJECT_UNREF (mlocale__collate); + mlocale__collate = locale; + } + else if (name && (category == LC_ALL || category == LC_CTYPE)) + { + M17N_OBJECT_REF (locale); + M17N_OBJECT_UNREF (mlocale__ctype); + mlocale__ctype = locale; + } + if (name && (category == LC_ALL || category == LC_MESSAGES)) + { + M17N_OBJECT_REF (locale); + M17N_OBJECT_UNREF (mlocale__messages); + mlocale__messages = locale; + } + if (name && (category == LC_ALL || category == LC_TIME)) + { + M17N_OBJECT_REF (locale); + M17N_OBJECT_UNREF (mlocale__time); + mlocale__time = locale; + } + return locale; +} + +/*=*/ + +/***en + @brief Get the value of a locale property. + + The mlocale_get_prop () function returns the value of a property + $KEY of local $LOCALE. $KEY must be #Mname, #Mlanguage, + #Mterritory, #Mcodeset, #Mmodifier, or #Mcoding. */ + +/***ja + @brief ��������ץ��ѥƥ����ͤ�����. + + �ؿ� mlocale_get_prop () �ϡ��������� $LOCALE �� $KEY �ץ��ѥƥ����ͤ��֤��� + $KEY �� #Mname, #Mlanguage, #Mterritory, #Mcodeset, #Mmodifier, + #Mcoding �Τ����줫�Ǥ��롣 */ + +MSymbol +mlocale_get_prop (MLocale *locale, MSymbol key) +{ + if (key == Mcoding) + return locale->coding; + if (key == Mname) + return locale->name; + if (key == Mlanguage) + return locale->language; + if (key == Mterritory) + return locale->territory; + if (key == Mcodeset) + return locale->codeset; + if (key == Mmodifier) + return locale->modifier; + return Mnil; +} + +/*=*/ +/***en + @brief Format date and time. + + The mtext_ftime () function formats the broken-down time $TM + according to the format specification $FORMAT and append the + result to the M-text $MT. The formating is done according to the + locale $LOCALE (if not NULL) or the current locale (LC_TIME). + + The meaning of the arguments $TM and $FORMAT are the same as those + of strftime (). + + @seealso + strftime (). +*/ +/***ja + @brief ���դȻ��֤�ե����ޥåȤ���. + + �ؿ� mtext_ftime () �ϻ���ǡ��� (broken-down time) $TM ��$FORMAT + �ǻ��ꤵ�줿���������񤷡���̤�M-text $MT ���ղä��롣�ե����ޥåȤ� + NULL �Ǥʤ���� �������� $LOCALE �ˡ��ޤ��ϸ��ߤΥ�������(LC_TIME) �˽����� + + ���� $TM �� $FORMAT �ΰ�̣�� strftime () �ξ���Ʊ���� + + @seealso + strftime (). +*/ + +int +mtext_ftime (MText *mt, const char *format, const struct tm *tm, + MLocale *locale) +{ + int bufsize; + unsigned char *buf; + size_t nbytes, nchars; + char *current_locale = NULL; + + if (locale) + { + char *str = setlocale (LC_TIME, NULL); + int len = strlen (str) + 1; + + current_locale = alloca (len); + memcpy (current_locale, str, len); + mlocale_set (LC_TIME, msymbol_name (locale->name)); + } + + bufsize = 1024; + while (1) + { + MTABLE_ALLOCA (buf, bufsize, MERROR_MTEXT); + buf[0] = 1; + nbytes = strftime ((char *) buf, bufsize, format, tm); + if (nbytes > 0 + || ! buf[0]) + break; + bufsize *= 2; + } + + if (nbytes > 0) + { + MText *work = decode_locale (buf, nbytes, mlocale__time); + + if (work) + { + nchars = work->nchars; + mtext_cat (mt, work); + M17N_OBJECT_UNREF (work); + } + else + nchars = 0; + } + else + nchars = 0; + + if (current_locale) + mlocale_set (LC_TIME, current_locale); + + return nchars; +} + +/*=*/ + +/***en + @brief Get an environment variable. + + The mtext_getenv () function searches the environment variable + list for a string that matches the string pointed to by $NAME. + + If there is a match, the function decodes the value according to + the current locale (LC_CTYPE) into an M-text, and return that + M-text. + + If there is no match, the function returns NULL. */ +/***ja + @brief �Ķ��ѿ�������. + + �ؿ� mtext_getenv () �� $NAME + �ǻؤ����ʸ����ȹ��פ���ʸ�����Ķ��ѿ��Υꥹ���椫��õ���� + + ���Ĥ��ä����ˤϡ������ͤ򸽺ߤΥ�������(LC_CTYPE) �˽��ä� + M-text �˥ǥ����ɤ�������M-text ���֤��� + + ���Ĥ���ʤ���С�NULL ���֤��� */ + +MText * +mtext_getenv (const char *name) +{ + char *p = getenv (name); + + if (!p) + return NULL; + return decode_locale ((unsigned char *) p, strlen (p), mlocale__ctype); +} + +/*=*/ + +/***en + @brief Change or add an environment variable. + + The mtext_putenv () function changes or adds the value of + environment variables according to M-text $MT. It calls the + function putenv with an argument generated by encoding + $MT according to the current locale (LC_CTYPE). + + @return + This function returns zero on success, or -1 if an error + occurs. */ +/***ja + @brief �Ķ��ѿ����ѹ����ɲä���. + + �ؿ� mtext_putenv () �� M-text $MT + �˽��äơ��Ķ��ѿ����ͤ��ѹ��������ɲä����ꤹ�롣���δؿ��ϡ����ߤΥ������� + (LC_CTYPE) �˽��ä�$MT �򥨥󥳡��ɤ������������Ȥ��ƴؿ� putenv ��Ƥ֡� + + @return + ���δؿ��ϡ������������ˤ� 0 �򡢥��顼��������� -1 ���֤��� + */ + + +int +mtext_putenv (MText *mt) +{ + unsigned char buf[1024]; + int size = 1024; + unsigned char *newbuf; + int result; + + newbuf = encode_locale (mt, buf, &size, mlocale__ctype); + result = putenv ((char *) newbuf); + if (buf != newbuf) + free (newbuf); + return result; +} + +/*=*/ + +/***en + @brief Compare two M-texts using the current locale. + + The mtext_coll () function compares the two M-texts $MT1 and $MT2. + It returns an integer less than, equal to, or greater than zero if + $MT1 is found, respectively, to be less than, to match, or to be + greater than $MT2. The comparison is based on texts as + appropriate for the current locale (LC_COLLATE). + + This function makes use of information that is automatically + cached in the M-texts as a text property. So, the second call of + this function with $MT1 or $MT2 finishes faster than the first + call. */ +/***ja + @brief ���ߤΥ���������Ѥ��ƣ��Ĥ� M-text ����Ӥ���. + + �ؿ� mtext_coll () �ϣ��Ĥ� M-text $MT1 �� $MT2 + ����Ӥ��롣����ͤ����������, 0, ���������ͤΤ����줫�Ǥ��ꡢ���줾�� + $MT1 �� $MT2 ��꾮������Ʊ�����礭�������������롣��Ӥϸ��ߤΥ������� + (LC_COLLATE) �˴�Ť��ƹԤ��롣 + + ���δؿ��� M-text + �Υƥ����ȥץ��ѥƥ��Ȥ��Ƽ�ưŪ�˥���å��夵����������Ѥ���Τǡ������ܰʹߤ�Ʊ����Ӥϣ����ܤ��®���¹Ԥ���롣 */ + +int +mtext_coll (MText *mt1, MText *mt2) +{ + char *str1, *str2; + + if (mt1->nchars == 0) + return (mt2->nchars == 0 ? 0 : -1); + else if (mt2->nchars == 0) + return 1; + + str1 = get_xfrm (mt1); + str2 = get_xfrm (mt2); + return strcoll (str1, str2); +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/m17n-X.c b/src/m17n-X.c new file mode 100644 index 0000000..c7cd013 --- /dev/null +++ b/src/m17n-X.c @@ -0,0 +1,2700 @@ +/* m17n-X.c -- implementation of the GUI API on X Windows. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#include "config.h" + +#ifdef HAVE_X11 + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_XFT2 +#include +#include +#endif /* HAVE_XFT2 */ + +#include "m17n-gui.h" +#include "m17n-X.h" +#include "m17n-misc.h" +#include "internal.h" +#include "internal-gui.h" +#include "symbol.h" +#include "input.h" +#include "font.h" +#include "fontset.h" +#include "face.h" + +typedef struct +{ + /* Common header for the m17n object. */ + M17NObject control; + + Display *display; + + /* If nonzero, is opened by this library. Thus it should + be closed on freeing this structure. */ + int auto_display; + + /** List of available X-core fonts on the display. Keys are + registries and values are plists whose keys are families and + values are pointers to MFont. */ + MPlist *font_list; + + /** Nonzero means that already contains all available + fonts on the display. */ + int all_fonts_scaned; + + /** Modifier bit masks of the display. */ + int meta_mask; + int alt_mask; + int super_mask; + int hyper_mask; + int altgr_mask; + + Atom MULE_BASELINE_OFFSET; + Atom AVERAGE_WIDTH; +} MDisplayInfo; + +/* Anchor of the chain of MDisplayInfo objects. */ +static MPlist *display_info_list; + + +/* Color value and the corresponding GC. */ +typedef struct +{ + unsigned int rgb; /* (red << 16) | (green << 8) | blue */ + GC gc; +} RGB_GC; + +enum gc_index + { + GC_INVERSE, + GC_NORMAL = GC_INVERSE + 7, + GC_HLINE, + GC_BOX_TOP, + GC_BOX_BOTTOM, + GC_BOX_LEFT, + GC_BOX_RIGHT, + GC_MAX + }; + +typedef struct +{ + int rgb_fore; + int rgb_back; + /* The first 8 elements are indexed by an intensity for + anti-aliasing. The 2nd to 7th are created on demand. */ + GC gc[GC_MAX]; +#ifdef HAVE_XFT2 + XftColor xft_color_fore, xft_color_back; +#endif +} GCInfo; + +typedef struct +{ + /* Common header for the m17n object. */ + M17NObject control; + + MDisplayInfo *display_info; + + int screen_num; + + Drawable drawable; + + unsigned depth; + + Colormap cmap; + + GC scratch_gc; + + int resy; + +#ifdef HAVE_XFT2 + XftDraw *xft_draw; +#endif + + /** List of pointers to realized faces on the frame. */ + MPlist *realized_face_list; + + /* List of single element whose value is a root of chain of realized + fonts. */ + MPlist *realized_font_list; + + /** List of pointers to realized fontsets on the frame. */ + MPlist *realized_fontset_list; + + /** List of XColors vs GCs on the frame. */ + MPlist *gc_list; +} MWDevice; + +static MPlist *device_list; + +static MSymbol M_iso8859_1, M_iso10646_1; + +#define FRAME_DEVICE(frame) ((MWDevice *) (frame)->device) +#define FRAME_DISPLAY(frame) (FRAME_DEVICE (frame)->display_info->display) +#define FRAME_SCREEN(frame) (FRAME_DEVICE (frame)->screen_num) +#define FRAME_CMAP(frame) (FRAME_DEVICE (frame)->cmap) +#define FRAME_VISUAL(frame) DefaultVisual (FRAME_DISPLAY (frame), \ + FRAME_SCREEN (frame)) + +#define DEFAULT_FONT "-*-*-medium-r-normal--13-*-*-*-c-*-iso8859-1" + +typedef struct +{ + String font; + String foreground; + String background; + Boolean reverse_video; +} AppData, *AppDataPtr; + +static void +free_display_info (void *object) +{ + MDisplayInfo *disp_info = (MDisplayInfo *) object; + MPlist *plist, *pl; + + MPLIST_DO (plist, disp_info->font_list) + { + MPLIST_DO (pl, MPLIST_VAL (plist)) + free (MPLIST_VAL (pl)); + M17N_OBJECT_UNREF (MPLIST_VAL (plist)); + } + M17N_OBJECT_UNREF (disp_info->font_list); + + if (disp_info->auto_display) + XCloseDisplay (disp_info->display); + + free (object); +} + +static void +free_device (void *object) +{ + MWDevice *device = object; + MPlist *plist; + + for (plist = device->realized_fontset_list; + mplist_key (plist) != Mnil; plist = mplist_next (plist)) + mfont__free_realized_fontset ((MRealizedFontset *) mplist_value (plist)); + M17N_OBJECT_UNREF (device->realized_fontset_list); + + if (MPLIST_VAL (device->realized_font_list)) + mfont__free_realized (MPLIST_VAL (device->realized_font_list)); + M17N_OBJECT_UNREF (device->realized_font_list); + + MPLIST_DO (plist, device->realized_face_list) + { + MRealizedFace *rface = MPLIST_VAL (plist); + + free (rface->info); + mface__free_realized (rface); + } + M17N_OBJECT_UNREF (device->realized_face_list); + + MPLIST_DO (plist, device->gc_list) + { + XFreeGC (device->display_info->display, + ((RGB_GC *) MPLIST_VAL (plist))->gc); + free (MPLIST_VAL (plist)); + } + M17N_OBJECT_UNREF (device->gc_list); + XFreeGC (device->display_info->display, device->scratch_gc); + +#ifdef HAVE_XFT2 + XftDrawDestroy (device->xft_draw); +#endif + + XFreePixmap (device->display_info->display, device->drawable); + M17N_OBJECT_UNREF (device->display_info); + free (object); +} + + +static void +find_modifier_bits (MDisplayInfo *disp_info) +{ + Display *display = disp_info->display; + XModifierKeymap *mods; + KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L); + KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R); + KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L); + KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R); + KeyCode super_l = XKeysymToKeycode (display, XK_Super_L); + KeyCode super_r = XKeysymToKeycode (display, XK_Super_R); + KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L); + KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R); +#ifdef XK_XKB_KEYS + KeyCode altgr = XKeysymToKeycode (display, XK_ISO_Level3_Shift); +#endif + int i, j; + + mods = XGetModifierMapping (display); + /* We skip the first three sets for Shift, Lock, and Control. The + remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */ + for (i = 3; i < 8; i++) + for (j = 0; j < mods->max_keypermod; j++) + { + KeyCode code = mods->modifiermap[i * mods->max_keypermod + j]; + + if (! code) + continue; + if (code == meta_l || code == meta_r) + disp_info->meta_mask |= (1 << i); + else if (code == alt_l || code == alt_r) + disp_info->alt_mask |= (1 << i); + else if (code == super_l || code == super_r) + disp_info->super_mask |= (1 << i); + else if (code == hyper_l || code == hyper_r) + disp_info->hyper_mask |= (1 << i); +#ifdef XK_XKB_KEYS + else if (code == altgr) + disp_info->altgr_mask |= (1 << i); +#endif + } + + /* If meta keys are not in any modifier, use alt keys as meta + keys. */ + if (! disp_info->meta_mask) + { + disp_info->meta_mask = disp_info->alt_mask; + disp_info->alt_mask = 0; + } + /* If both meta and alt are assigned to the same modifier, give meta + keys priority. */ + if (disp_info->meta_mask & disp_info->alt_mask) + disp_info->alt_mask &= ~disp_info->meta_mask; + + XFreeModifiermap (mods); +} + +static RGB_GC * +get_rgb_gc (MWDevice *device, XColor *xcolor) +{ + int rgb = (((xcolor->red >> 8) << 16) | ((xcolor->green >> 8) << 8) + | (xcolor->blue >> 8)); + MPlist *plist; + RGB_GC *rgb_gc; + unsigned long valuemask = GCForeground; + XGCValues values; + + MPLIST_DO (plist, device->gc_list) + { + rgb_gc = MPLIST_VAL (plist); + + if (rgb_gc->rgb == rgb) + return rgb_gc; + if (rgb_gc->rgb > rgb) + break; + } + + if (! XAllocColor (device->display_info->display, device->cmap, xcolor)) + return NULL; + + rgb_gc = malloc (sizeof (RGB_GC)); + rgb_gc->rgb = rgb; + values.foreground = xcolor->pixel; + rgb_gc->gc = XCreateGC (device->display_info->display, + device->drawable, valuemask, &values); + mplist_push (plist, Mt, rgb_gc); + return rgb_gc; +} + +static GC +get_gc (MFrame *frame, MSymbol color, int for_foreground, int *rgb_ret) +{ + MWDevice *device = FRAME_DEVICE (frame); + XColor xcolor; + RGB_GC *rgb_gc; + + if (color == Mnil) + { + if (frame->rface) + goto no_color; + color = for_foreground ? frame->foreground : frame->background; + } + if (! XParseColor (FRAME_DISPLAY (frame), device->cmap, + msymbol_name (color), &xcolor)) + goto no_color; + rgb_gc = get_rgb_gc (device, &xcolor); + if (! rgb_gc) + goto no_color; + if (rgb_ret) + *rgb_ret = rgb_gc->rgb; + return rgb_gc->gc; + + no_color: + { + GCInfo *info = frame->rface->info; + GC gc; + int rgb; + + if (for_foreground) + rgb = info->rgb_fore, gc = info->gc[GC_NORMAL]; + else + rgb = info->rgb_back, gc = info->gc[GC_INVERSE]; + if (rgb_ret) + *rgb_ret = rgb; + return gc; + } +} + +static GC +get_gc_for_anti_alias (MWDevice *device, GCInfo *info, int intensity) +{ + int rgb_fore, rgb_back; + XColor xcolor; + RGB_GC *rgb_gc; + GC gc; + + if (info->gc[intensity]) + return info->gc[intensity]; + + rgb_fore = info->rgb_fore, rgb_back = info->rgb_back; + xcolor.red = ((((rgb_fore & 0xFF0000) >> 16) * intensity + + ((rgb_back & 0xFF0000) >> 16) * (7 - intensity)) / 7) << 8; + xcolor.green = ((((rgb_fore & 0xFF00) >> 8) * intensity + + ((rgb_back & 0xFF00) >> 8) * (7 - intensity)) / 7) << 8; + xcolor.blue = (((rgb_fore & 0xFF) * intensity + + (rgb_back & 0xFF) * (7 - intensity)) / 7) << 8; + rgb_gc = get_rgb_gc (device, &xcolor); + if (rgb_gc) + gc = rgb_gc->gc; + else + gc =get_gc_for_anti_alias (device, info, + intensity < 4 ? intensity - 1 : intensity + 1); + return (info->gc[intensity] = gc); +} + +static GC +set_region (MFrame *frame, GC gc, MDrawRegion region) +{ + unsigned long valuemask = GCForeground; + + XCopyGC (FRAME_DISPLAY (frame), gc, valuemask, + FRAME_DEVICE (frame)->scratch_gc); + XSetRegion (FRAME_DISPLAY (frame), FRAME_DEVICE (frame)->scratch_gc, region); + return FRAME_DEVICE (frame)->scratch_gc; +} + + +/** X font handler */ + +static MFont *xfont_select (MFrame *, MFont *, int); +static MRealizedFont *xfont_open (MFrame *, MFont *, MFont *, MRealizedFont *); +static void xfont_find_metric (MRealizedFont *, MGlyphString *, int, int); +static int xfont_has_char (MFrame *, MFont *, MFont *, int, unsigned); +static unsigned xfont_encode_char (MFrame *, MFont *, MFont *, unsigned); +static void xfont_render (MDrawWindow, int, int, MGlyphString *, + MGlyph *, MGlyph *, int, MDrawRegion); +static int xfont_list (MFrame *, MPlist *, MFont *, int); +static void xfont_list_family_names (MFrame *, MPlist *); +static int xfont_check_capability (MRealizedFont *rfont, MSymbol capability); + +static MFontDriver xfont_driver = + { xfont_select, xfont_open, + xfont_find_metric, xfont_has_char, xfont_encode_char, + xfont_render, xfont_list, xfont_list_family_names, xfont_check_capability + }; + +static int +font_compare (const void *p1, const void *p2) +{ + return strcmp (*(char **) p1, *(char **) p2); +} + +static MPlist * +xfont_registry_list (MFrame *frame, MSymbol registry) +{ + MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info; + MPlist *font_list = disp_info->font_list; + MPlist *plist, *p; + char pattern[1024]; + char **font_names, **names; + int nfonts; + int i, j; + MFont font; + int for_full_width; + + plist = mplist_get (font_list, registry); + if (plist) + return plist; + p = plist = mplist (); + mplist_add (font_list, registry, plist); + sprintf (pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", msymbol_name (registry)); + font_names = XListFonts (disp_info->display, pattern, 0x8000, &nfonts); + if (nfonts == 0) + return plist; + { + char *reg_name = msymbol_name (registry); + + for_full_width = (strncmp (reg_name, "jis", 3) == 0 + || strncmp (reg_name, "gb", 2) == 0 + || strncmp (reg_name, "big5", 4) == 0 + || strncmp (reg_name, "ksc", 3) == 0); + } + names = alloca (sizeof (char *) * nfonts); + memcpy (names, font_names, sizeof (char *) * nfonts); + qsort (names, nfonts, sizeof (char *), font_compare); + MFONT_INIT (&font); + for (i = 0; i < nfonts; i++) + if (mfont__parse_name_into_font (names[i], Mx, &font) == 0 + && (font.size > 0 || font.property[MFONT_RESY] == 0)) + { + MSymbol family = FONT_PROPERTY (&font, MFONT_FAMILY); + MFont *fontx; + unsigned sizes[256]; + int nsizes = 0; + int limit; + int size, normal_size; + char *base_end; + int base_len; + int fields; + + /* Calculate how many bytes to compare to detect fonts of the + same base name. */ + for (base_end = names[i], fields = 0; *base_end; base_end++) + if (*base_end == '-' + && ++fields == 7 /* PIXEL_SIZE */) + break; + base_len = base_end - names[i] + 1; + + size = font.size / 10; + sizes[nsizes++] = size; + normal_size = (size >= 6 && size <= 29); + limit = (i + 256 < nfonts ? i + 256 : nfonts); + for (j = i + 1; j < limit && ! memcmp (names[i], names[j], base_len); + i = j++) + if (mfont__parse_name_into_font (names[j], Mx, &font) == 0 + && (font.size > 0 || font.property[MFONT_RESY] == 0)) + { + size = font.size / 10; + sizes[nsizes++] = size; + normal_size |= (size >= 6 && size <= 29); + } + + font.for_full_width = for_full_width; + font.type = MFONT_TYPE_OBJECT; + font.source = MFONT_SOURCE_X; + if (normal_size) + { + MSTRUCT_CALLOC (fontx, MERROR_WIN); + *fontx = font; + fontx->multiple_sizes = 1; + fontx->size = 0; + for (j = 0; j < nsizes; j++) + if (sizes[j] >= 6 && sizes[j] <= 29) + fontx->size |= 1 << (sizes[j] - 6); + p = mplist_add (p, family, fontx); + } + for (j = 0; j < nsizes; j++) + if (sizes[j] < 6 || sizes[j] > 29) + { + MSTRUCT_CALLOC (fontx, MERROR_WIN); + *fontx = font; + fontx->multiple_sizes = 0; + fontx->size = sizes[j] * 10; + if (sizes[j] == 0) + fontx->property[MFONT_RESY] = 0; + p = mplist_add (p, family, fontx); + } + } + XFreeFontNames (font_names); + return plist; +} + +static void +xfont_list_all (MFrame *frame) +{ + MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info; + MPlist *font_encoding_list, *p; + + if (disp_info->all_fonts_scaned) + return; + disp_info->all_fonts_scaned = 1; + font_encoding_list = mfont__encoding_list (); + if (! font_encoding_list) + return; + MPLIST_DO (p, font_encoding_list) + xfont_registry_list (frame, MPLIST_KEY (p)); +} + +typedef struct +{ + M17NObject control; + Display *display; + XFontStruct *xfont; +} MRealizedFontX; + +/* The X font driver function SELECT. */ + +static MFont * +xfont_select (MFrame *frame, MFont *font, int limited_size) +{ + MPlist *plist = mplist (), *pl; + int num = xfont_list (frame, plist, font, 0); + MFont *found = NULL; + + if (num > 0) + MPLIST_DO (pl, plist) + { + font = MPLIST_VAL (pl); + if (limited_size == 0 + || font->size == 0 + || font->size <= limited_size) + { + found = font; + break; + } + } + M17N_OBJECT_UNREF (plist); + return found; +} + +/* The X font driver function CLOSE. */ + +static void +close_xfont (void *object) +{ + MRealizedFontX *x_rfont = object; + + XFreeFont (x_rfont->display, x_rfont->xfont); + free (x_rfont); +} + +/* The X font driver function OPEN. */ + +static MRealizedFont * +xfont_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont) +{ + int size; + MRealizedFontX *x_rfont; + char *name; + Display *display = FRAME_DISPLAY (frame); + XFontStruct *xfont; + int mdebug_flag = MDEBUG_FONT; + MFont this; + + size = spec->size; + if (size) + { + int ratio = mfont_resize_ratio (font); + + if (ratio != 100) + size = size * ratio / 100; + } + else + size = 120; + + if (font->size) + { + /* non-scalable font */ + if (font->multiple_sizes) + { + int i; + + if (size < 60) + size = 60; + else if (size > 290) + size = 290; + for (i = size / 10 - 6; i >= 0; i--) + if (font->size & (1 << i)) + break; + if (i == 0) + for (i = size / 10 - 5; i < 24; i++) + if (font->size & (1 << i)) + break; + size = (i + 6) * 10; + } + else + size = font->size; + } + + if (rfont) + { + for (; rfont; rfont = rfont->next) + if (rfont->font == font && rfont->spec.size == size) + return rfont; + } + + this = *font; + this.multiple_sizes = 0; + this.size = size; + /* This never fail to generate a valid fontname. */ + name = mfont_unparse_name (&this, Mx); + xfont = XLoadQueryFont (FRAME_DISPLAY (frame), name); + if (! xfont) + { + MDEBUG_PRINT1 (" [XFONT] x %s\n", name); + free (name); + font->type = MFONT_TYPE_FAILURE; + return NULL; + } + M17N_OBJECT (x_rfont, close_xfont, MERROR_FONT_X); + x_rfont->display = display; + x_rfont->xfont = xfont; + MSTRUCT_CALLOC (rfont, MERROR_FONT_X); + rfont->id = msymbol (name); + rfont->spec = this; + rfont->spec.type = MFONT_TYPE_REALIZED; + rfont->spec.source = MFONT_SOURCE_X; + rfont->frame = frame; + rfont->font = font; + rfont->driver = &xfont_driver; + rfont->info = x_rfont; + { + MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info; + unsigned long value; + + rfont->baseline_offset + = (XGetFontProperty (xfont, disp_info->MULE_BASELINE_OFFSET, &value) + ? (int) (value << 6) : 0); + rfont->average_width + = (XGetFontProperty (xfont, disp_info->AVERAGE_WIDTH, &value) + ? (int) (value << 6) / 10 : 0); + } + rfont->ascent = (xfont->ascent << 6) + rfont->baseline_offset; + rfont->descent = (xfont->descent << 6) - rfont->baseline_offset; + rfont->max_advance = xfont->max_bounds.width << 6; + rfont->x_ppem = rfont->y_ppem = size / 10; + rfont->fontp = xfont; + rfont->next = MPLIST_VAL (frame->realized_font_list); + MPLIST_VAL (frame->realized_font_list) = rfont; + MDEBUG_PRINT1 (" [XFONT] o %s\n", name); + free (name); + return rfont; +} + + +/* The X font driver function FIND_METRIC. */ + +static void +xfont_find_metric (MRealizedFont *rfont, MGlyphString *gstring, + int from, int to) +{ + XFontStruct *xfont = rfont->fontp; + MGlyph *g = MGLYPH (from), *gend = MGLYPH (to); + + for (; g != gend; g++) + if (! g->g.measured) + { + if (g->g.code == MCHAR_INVALID_CODE) + { + g->g.lbearing = xfont->max_bounds.lbearing << 6; + g->g.rbearing = xfont->max_bounds.rbearing << 6; + g->g.xadv = xfont->max_bounds.width << 6; + g->g.ascent = xfont->ascent << 6; + g->g.descent = xfont->descent << 6; + } + else + { + int byte1 = g->g.code >> 8, byte2 = g->g.code & 0xFF; + XCharStruct *pcm = NULL; + + if (xfont->per_char != NULL) + { + if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0) + { + if (byte1 == 0 + && byte2 >= xfont->min_char_or_byte2 + && byte2 <= xfont->max_char_or_byte2) + pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2; + } + else + { + if (byte1 >= xfont->min_byte1 + && byte1 <= xfont->max_byte1 + && byte2 >= xfont->min_char_or_byte2 + && byte2 <= xfont->max_char_or_byte2) + { + pcm = (xfont->per_char + + ((xfont->max_char_or_byte2 + - xfont->min_char_or_byte2 + 1) + * (byte1 - xfont->min_byte1)) + + (byte2 - xfont->min_char_or_byte2)); + } + } + } + + if (pcm) + { + g->g.lbearing = pcm->lbearing << 6; + g->g.rbearing = pcm->rbearing << 6; + g->g.xadv = pcm->width << 6; + g->g.ascent = pcm->ascent << 6; + g->g.descent = pcm->descent << 6; + } + else + { + /* If the per_char pointer is null, all glyphs between + the first and last character indexes inclusive have + the same information, as given by both min_bounds and + max_bounds. */ + g->g.lbearing = 0; + g->g.rbearing = xfont->max_bounds.width << 6; + g->g.xadv = xfont->max_bounds.width << 6; + g->g.ascent = xfont->ascent << 6; + g->g.descent = xfont->descent << 6; + } + } + g->g.yadv = 0; + g->g.ascent += rfont->baseline_offset; + g->g.descent -= rfont->baseline_offset; + g->g.measured = 1; + } +} + + +static int +xfont_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code) +{ + return (xfont_encode_char (frame, font, spec, code) != MCHAR_INVALID_CODE); +} + +/* The X font driver function GET_GLYPH_ID. */ + +static unsigned +xfont_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code) +{ + MRealizedFont *rfont; + XFontStruct *xfont; + unsigned min_byte1, max_byte1, min_byte2, max_byte2; + int all_chars_exist; + + if (font->type == MFONT_TYPE_REALIZED) + rfont = (MRealizedFont *) font; + else if (font->type == MFONT_TYPE_OBJECT) + { + for (rfont = MPLIST_VAL (frame->realized_font_list); rfont; + rfont = rfont->next) + if (rfont->font == font) + break; + if (! rfont) + { + rfont = xfont_open (frame, font, spec, NULL); + if (! rfont) + return MCHAR_INVALID_CODE; + } + } + else + MFATAL (MERROR_FONT_X); + xfont = rfont->fontp; + all_chars_exist = (! xfont->per_char || xfont->all_chars_exist == True); + min_byte1 = xfont->min_byte1; + max_byte1 = xfont->max_byte1; + min_byte2 = xfont->min_char_or_byte2; + max_byte2 = xfont->max_char_or_byte2; + + if (min_byte1 == 0 && max_byte1 == 0) + { + XCharStruct *pcm; + + if (code < min_byte2 || code > max_byte2) + return MCHAR_INVALID_CODE; + if (all_chars_exist) + return code; + pcm = xfont->per_char + (code - min_byte2); + return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing) + ? code : MCHAR_INVALID_CODE); + } + else + { + unsigned byte1 = code >> 8, byte2 = code & 0xFF; + XCharStruct *pcm; + + if (byte1 < min_byte1 || byte1 > max_byte1 + || byte2 < min_byte2 || byte2 > max_byte2) + return MCHAR_INVALID_CODE; + + if (all_chars_exist) + return code; + pcm = xfont->per_char + ((byte1 - min_byte1) * (max_byte2 - min_byte2 + 1) + + (byte2 - min_byte2)); + return ((pcm->width > 0 || pcm->rbearing != pcm->lbearing) + ? code : MCHAR_INVALID_CODE); + } +} + +/* The X font driver function RENDER. */ + +static void +xfont_render (MDrawWindow win, int x, int y, MGlyphString *gstring, + MGlyph *from, MGlyph *to, int reverse, MDrawRegion region) +{ + MRealizedFace *rface = from->rface; + Display *display = FRAME_DISPLAY (rface->frame); + XChar2b *code; + GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL]; + MGlyph *g; + int i; + int baseline_offset; + + if (from == to) + return; + + baseline_offset = rface->rfont->baseline_offset >> 6; + if (region) + gc = set_region (rface->frame, gc, region); + XSetFont (display, gc, ((XFontStruct *) rface->rfont->fontp)->fid); + code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from)); + for (i = 0, g = from; g < to; i++, g++) + { + code[i].byte1 = g->g.code >> 8; + code[i].byte2 = g->g.code & 0xFF; + } + + g = from; + while (g < to) + { + if (g->type == GLYPH_PAD) + x += g++->g.xadv; + else if (g->type == GLYPH_SPACE) + for (; g < to && g->type == GLYPH_SPACE; g++) + x += g->g.xadv; + else if (! g->rface->rfont) + { + if ((g->g.c >= 0x200B && g->g.c <= 0x200F) + || (g->g.c >= 0x202A && g->g.c <= 0x202E)) + x += g++->g.xadv; + else + { + /* As a font is not found for this character, draw an + empty box. */ + int box_width = g->g.xadv; + int box_height = gstring->ascent + gstring->descent; + + if (box_width > 4) + box_width -= 2; + if (box_height > 4) + box_height -= 2; + XDrawRectangle (display, (Window) win, gc, + x, y - gstring->ascent, box_width, box_height); + x += g++->g.xadv; + } + } + else if (g->g.xoff != 0 || g->g.yoff != 0 || g->right_padding) + { + XDrawString16 (display, (Window) win, gc, + x + g->g.xoff, y + g->g.yoff - baseline_offset, + code + (g - from), 1); + x += g->g.xadv; + g++; + } + else + { + int orig_x = x; + int code_idx = g - from; + + for (i = 0; + g < to && g->type == GLYPH_CHAR && g->g.xoff == 0 && g->g.yoff == 0; + i++, g++) + x += g->g.xadv; + XDrawString16 (display, (Window) win, gc, + orig_x, y - baseline_offset, code + code_idx, i); + } + } +} + +static int +xfont_list (MFrame *frame, MPlist *plist, MFont *font, int maxnum) +{ + MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info; + MSymbol registry = font ? FONT_PROPERTY (font, MFONT_REGISTRY) : Mnil; + MSymbol family = font ? FONT_PROPERTY (font, MFONT_FAMILY) : Mnil; + int size = font ? font->size : 0; + MPlist *pl, *p; + int num = 0; + int mdebug_flag = MDEBUG_FONT; + + MDEBUG_PRINT2 (" [X-FONT] listing %s-%s...", + family ? msymbol_name (family) : "*", + registry ? msymbol_name (registry) : "*"); + + if (registry == Mnil) + xfont_list_all (frame); + else + xfont_registry_list (frame, registry); + + MPLIST_DO (pl, disp_info->font_list) + if (registry == Mnil || registry == MPLIST_KEY (pl)) + { + MPLIST_DO (p, MPLIST_VAL (pl)) + if (family == Mnil || family == MPLIST_KEY (p)) + { + MFont *fontx = MPLIST_VAL (p); + + if (! font || (mfont__match_p (fontx, font, MFONT_REGISTRY))) + { + if (fontx->size != 0 && size) + { + if (fontx->multiple_sizes) + { + if (size < 60 || size > 290 + || ! (fontx->size & (1 << (size / 10 - 6)))) + continue; + } + else if (fontx->size != size) + continue; + } + mplist_push (plist, MPLIST_KEY (p), fontx); + num++; + if (maxnum > 0 && maxnum == num) + goto done; + } + } + } + + done: + MDEBUG_PRINT1 (" %d found\n", num); + return num; +} + +static void +xfont_list_family_names (MFrame *frame, MPlist *plist) +{ + MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info; + char **font_names; + int i, nfonts; + MSymbol last_family = Mnil; + + font_names = XListFonts (disp_info->display, + "-*-*-*-*-*-*-*-*-*-*-*-*-*-*", 0x8000, &nfonts); + for (i = 0; i < nfonts; i++) + { + MSymbol family; + char foundry[256], fam[256]; + MPlist *p; + + if (sscanf (font_names[i], "-%s-%s-", foundry, fam) < 2) + continue; + family = msymbol (fam); + if (family == last_family) + continue; + last_family = family; + + MPLIST_DO (p, plist) + { + MSymbol sym = MPLIST_SYMBOL (p); + + if (sym == family) + break; + if (strcmp (MSYMBOL_NAME (sym), fam) > 0) + { + mplist_push (p, Msymbol, family); + break; + } + } + if (MPLIST_TAIL_P (p)) + mplist_push (p, Msymbol, family); + } + if (font_names) + XFreeFontNames (font_names); +} + +static int +xfont_check_capability (MRealizedFont *rfont, MSymbol capability) +{ + /* Currently X font driver doesn't support any capability. */ + return -1; +} + + +/* Xft Handler */ + +#ifdef HAVE_XFT2 + +typedef struct +{ + M17NObject control; + FT_Face ft_face; /* This must be the 2nd member. */ + Display *display; + XftFont *font_aa; + XftFont *font_no_aa; + /* Pointer to MRealizedFontFT */ + void *info; +} MRealizedFontXft; + +static MRealizedFont *xft_open (MFrame *frame, MFont *font, MFont *spec, + MRealizedFont *); +static int xft_has_char (MFrame *frame, MFont *font, MFont *spec, + int c, unsigned code); +static unsigned xft_encode_char (MFrame *frame, MFont *font, MFont *spec, + unsigned code); +static void xft_find_metric (MRealizedFont *, MGlyphString *, int, int); +static void xft_render (MDrawWindow, int, int, MGlyphString *, + MGlyph *, MGlyph *, int, MDrawRegion); +static int xft_check_capability (MRealizedFont *rfont, MSymbol capability); +static int xft_check_otf (MFLTFont *font, MFLTOtfSpec *spec); +static int xft_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, + MFLTGlyphString *in, int from, int to, + MFLTGlyphString *out, + MFLTGlyphAdjustment *adjustment); +static int xft_try_otf (MFLTFont *font, MFLTOtfSpec *spec, + MFLTGlyphString *in, int from, int to); +static int xft_iterate_otf_feature (struct _MFLTFont *font, MFLTOtfSpec *spec, + int from, int to, unsigned char *table); + + +static MFontDriver xft_driver = + { NULL, xft_open, + xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL, NULL, + xft_check_capability, NULL, NULL, xft_check_otf, xft_drive_otf, xft_try_otf, +#ifdef HAVE_OTF + xft_iterate_otf_feature +#endif /* HAVE_OTF */ + }; + +static void +close_xft (void *object) +{ + MRealizedFontXft *rfont_xft = object; + + if (rfont_xft->font_aa) + XftFontClose (rfont_xft->display, rfont_xft->font_aa); + if (rfont_xft->font_no_aa) + XftFontClose (rfont_xft->display, rfont_xft->font_no_aa); + M17N_OBJECT_UNREF (rfont_xft->info); + free (rfont_xft); +} + + +static XftFont * +xft_open_font (Display *display, MSymbol file, double size, + FcBool anti_alias) +{ + FcPattern *pattern; + XftFont *font; + + pattern = FcPatternCreate (); + FcPatternAddString (pattern, FC_FILE, (FcChar8 *) msymbol_name (file)); + FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size); + FcPatternAddBool (pattern, FC_ANTIALIAS, anti_alias); + font = XftFontOpenPattern (display, pattern); + return font; +} + + +static MRealizedFont * +xft_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont) +{ + Display *display = FRAME_DISPLAY (frame); + int reg = spec->property[MFONT_REGISTRY]; + FT_Face ft_face; + MRealizedFontXft *rfont_xft; + FcBool anti_alias = FRAME_DEVICE (frame)->depth > 1 ? FcTrue : FcFalse; + int size; + XftFont *xft_font; + int ascent, descent, max_advance, average_width, baseline_offset; + + if (font->size) + /* non-scalable font */ + size = font->size; + else if (spec->size) + { + int ratio = mfont_resize_ratio (font); + + size = ratio == 100 ? spec->size : spec->size * ratio / 100; + } + else + size = 120; + + if (rfont) + { + MRealizedFont *save = NULL; + + for (; rfont; rfont = rfont->next) + if (rfont->font == font + && (rfont->font->size ? rfont->font->size == size + : rfont->spec.size == size) + && rfont->spec.property[MFONT_REGISTRY] == reg) + { + if (! save) + save = rfont; + if (rfont->driver == &xft_driver) + return rfont; + } + rfont = save; + } + rfont = (mfont__ft_driver.open) (frame, font, spec, rfont); + if (! rfont) + return NULL; + ascent = rfont->ascent; + descent = rfont->descent; + max_advance = rfont->max_advance; + average_width = rfont->average_width; + baseline_offset = rfont->baseline_offset; + spec = &rfont->spec; + ft_face = rfont->fontp; + xft_font = xft_open_font (display, font->file, size / 10, anti_alias); + if (! xft_font) + return NULL; + M17N_OBJECT (rfont_xft, close_xft, MERROR_WIN); + rfont_xft->display = display; + if (anti_alias == FcTrue) + rfont_xft->font_aa = xft_font; + else + rfont_xft->font_no_aa = xft_font; + rfont_xft->ft_face = ft_face; + rfont_xft->info = rfont->info; + M17N_OBJECT_REF (rfont->info); + MSTRUCT_CALLOC (rfont, MERROR_FONT_X); + rfont->id = font->file; + rfont->spec = *spec; + rfont->spec.size = size; + rfont->frame = frame; + rfont->font = font; + rfont->driver = &xft_driver; + rfont->info = rfont_xft; + rfont->ascent = ascent; + rfont->descent = descent; + rfont->max_advance = max_advance; + rfont->average_width = average_width; + rfont->baseline_offset = baseline_offset; + rfont->x_ppem = ft_face->size->metrics.x_ppem; + rfont->y_ppem = ft_face->size->metrics.y_ppem; + rfont->fontp = xft_font; + rfont->next = MPLIST_VAL (frame->realized_font_list); + MPLIST_VAL (frame->realized_font_list) = rfont; + return rfont; +} + +static void +xft_find_metric (MRealizedFont *rfont, MGlyphString *gstring, + int from, int to) +{ + Display *display = FRAME_DISPLAY (rfont->frame); + XftFont *xft_font = rfont->fontp; + MGlyph *g = MGLYPH (from), *gend = MGLYPH (to); + + for (; g != gend; g++) + if (! g->g.measured) + { + if (g->g.code == MCHAR_INVALID_CODE) + { + g->g.lbearing = 0; + g->g.rbearing = xft_font->max_advance_width << 6; + g->g.xadv = g->g.rbearing << 6; + g->g.ascent = xft_font->ascent << 6; + g->g.descent = xft_font->descent << 6; + } + else + { + XGlyphInfo extents; + + XftGlyphExtents (display, xft_font, &g->g.code, 1, &extents); + g->g.lbearing = (- extents.x) << 6; + g->g.rbearing = (extents.width - extents.x) << 6; + g->g.xadv = extents.xOff << 6; + g->g.ascent = extents.y << 6; + g->g.descent = (extents.height - extents.y) << 6; + } + g->g.yadv = 0; + g->g.measured = 1; + } +} + +static int +xft_has_char (MFrame *frame, MFont *font, MFont *spec, int c, unsigned code) +{ + int result; + + if (font->type == MFONT_TYPE_REALIZED) + { + MRealizedFont *rfont = (MRealizedFont *) font; + MRealizedFontXft *rfont_xft = rfont->info; + + rfont->info = rfont_xft->info; + result = mfont__ft_driver.has_char (frame, font, spec, c, code); + rfont->info = rfont_xft; + } + else + result = mfont__ft_driver.has_char (frame, font, spec, c, code); + return result; +} + +static unsigned +xft_encode_char (MFrame *frame, MFont *font, MFont *spec, unsigned code) +{ + if (font->type == MFONT_TYPE_REALIZED) + { + MRealizedFont *rfont = (MRealizedFont *) font; + MRealizedFontXft *rfont_xft = rfont->info; + + rfont->info = rfont_xft->info; + code = mfont__ft_driver.encode_char (frame, font, spec, code); + rfont->info = rfont_xft; + } + else + code = mfont__ft_driver.encode_char (frame, font, spec, code); + return code; +} + +static void +xft_render (MDrawWindow win, int x, int y, + MGlyphString *gstring, MGlyph *from, MGlyph *to, + int reverse, MDrawRegion region) +{ + MRealizedFace *rface = from->rface; + MFrame *frame = rface->frame; + Display *display = FRAME_DISPLAY (frame); + MRealizedFont *rfont = rface->rfont; + MRealizedFontXft *rfont_xft = rfont->info; + XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw; + XftColor *xft_color = (! reverse + ? &((GCInfo *) rface->info)->xft_color_fore + : &((GCInfo *) rface->info)->xft_color_back); + int anti_alias = (gstring->control.anti_alias + && FRAME_DEVICE (frame)->depth > 1); + XftFont *xft_font; + MGlyph *g; + FT_UInt *glyphs; + int last_x; + int nglyphs; + + if (from == to) + return; + + if (anti_alias) + { + if (rfont_xft->font_aa) + xft_font = rfont_xft->font_aa; + else + { + double size = rfont->spec.size; + + xft_font = xft_open_font (display, rfont->spec.file, size / 10, + FcTrue); + if (xft_font) + rfont_xft->font_aa = xft_font; + else + xft_font = rfont->fontp; + } + } + else + { + if (rfont_xft->font_no_aa) + xft_font = rfont_xft->font_no_aa; + else + { + double size = rfont->spec.size; + + xft_font = xft_open_font (display, rfont->spec.file, size / 10, + FcTrue); + if (xft_font) + rfont_xft->font_no_aa = xft_font; + else + xft_font = rfont->fontp; + } + } + + XftDrawChange (xft_draw, (Drawable) win); + XftDrawSetClip (xft_draw, (Region) region); + + y -= rfont->baseline_offset >> 6; + glyphs = alloca (sizeof (FT_UInt) * (to - from)); + for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->g.xadv) + { + if (! g->g.adjusted && !g->left_padding && !g->right_padding) + glyphs[nglyphs++] = g->g.code; + else + { + if (nglyphs > 0) + XftDrawGlyphs (xft_draw, xft_color, xft_font, + last_x, y, glyphs, nglyphs); + nglyphs = 0; + XftDrawGlyphs (xft_draw, xft_color, xft_font, + x + g->g.xoff, y + g->g.yoff, (FT_UInt *) &g->g.code, 1); + last_x = x + g->g.xadv; + } + } + if (nglyphs > 0) + XftDrawGlyphs (xft_draw, xft_color, xft_font, last_x, y, glyphs, nglyphs); +} + +static int +xft_check_capability (MRealizedFont *rfont, MSymbol capability) +{ + MRealizedFontXft *rfont_xft = rfont->info; + int result; + + rfont->info = rfont_xft->info; + result = mfont__ft_driver.check_capability (rfont, capability); + rfont->info = rfont_xft; + return result; +} + +static int +xft_check_otf (MFLTFont *font, MFLTOtfSpec *spec) +{ + MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont; + MRealizedFontXft *rfont_xft = rfont->info; + int result; + + rfont->info = rfont_xft->info; + result = mfont__ft_driver.check_otf (font, spec); + rfont->info = rfont_xft; + return result; +} + +static int +xft_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, + MFLTGlyphString *in, int from, int to, + MFLTGlyphString *out, + MFLTGlyphAdjustment *adjustment) +{ + MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont; + MRealizedFontXft *rfont_xft = rfont->info; + int result; + + rfont->info = rfont_xft->info; + result = mfont__ft_driver.drive_otf (font, spec, in, from, to, out, + adjustment); + rfont->info = rfont_xft; + return result; +} + +static int +xft_try_otf (MFLTFont *font, MFLTOtfSpec *spec, + MFLTGlyphString *in, int from, int to) +{ + return xft_drive_otf (font, spec, in, from, to, NULL, NULL); +} + +#ifdef HAVE_OTF + +static int +xft_iterate_otf_feature (struct _MFLTFont *font, MFLTOtfSpec *spec, + int from, int to, unsigned char *table) +{ + MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont; + MRealizedFontXft *rfont_xft = rfont->info; + int result; + + rfont->info = rfont_xft->info; + result = mfont__ft_driver.iterate_otf_feature (font, spec, from, to, table); + rfont->info = rfont_xft; + return result; +} +#endif /* HAVE_OTF */ + +#endif /* HAVE_XFT2 */ + + +/* Functions for the device driver. */ + +static void +mwin__close_device (MFrame *frame) +{ + MWDevice *device = FRAME_DEVICE (frame); + + M17N_OBJECT_UNREF (device); +} + +static void * +mwin__device_get_prop (MFrame *frame, MSymbol key) +{ + MWDevice *device = FRAME_DEVICE (frame); + + if (key == Mdisplay) + return (void *) device->display_info->display; + if (key == Mscreen) + return (void *) ScreenOfDisplay(device->display_info->display, + device->screen_num); + if (key == Mcolormap) + return (void *) device->cmap; + if (key == Mdepth) + return (void *) device->depth; + return NULL; +} + +static void +mwin__realize_face (MRealizedFace *rface) +{ + MFrame *frame; + MSymbol foreground, background, videomode; + MFaceHLineProp *hline; + MFaceBoxProp *box; + GCInfo *info; + + if (rface != rface->ascii_rface) + { + rface->info = rface->ascii_rface->info; + return; + } + + frame = rface->frame; + MSTRUCT_CALLOC (info, MERROR_WIN); + + foreground = rface->face.property[MFACE_FOREGROUND]; + background = rface->face.property[MFACE_BACKGROUND]; + videomode = rface->face.property[MFACE_VIDEOMODE]; + if (! videomode) + videomode = frame->videomode; + if (videomode != Mreverse) + { + info->gc[GC_NORMAL] = get_gc (frame, foreground, 1, &info->rgb_fore); + info->gc[GC_INVERSE] = get_gc (frame, background, 0, &info->rgb_back); + } + else + { + info->gc[GC_NORMAL] = get_gc (frame, background, 0, &info->rgb_fore); + info->gc[GC_INVERSE] = get_gc (frame, foreground, 1, &info->rgb_back); + } +#ifdef HAVE_XFT2 + if (foreground == Mnil) + foreground = frame->foreground; + if (background == Mnil) + background = frame->background; + if (videomode == Mreverse) + { + MSymbol temp = foreground; + foreground = background; + background = temp; + } + if (! XftColorAllocName (FRAME_DISPLAY (frame), + FRAME_VISUAL (frame), + FRAME_CMAP (frame), + MSYMBOL_NAME (foreground), + &info->xft_color_fore)) + mdebug_hook (); + if (! XftColorAllocName (FRAME_DISPLAY (frame), + FRAME_VISUAL (frame), + FRAME_CMAP (frame), + MSYMBOL_NAME (background), + &info->xft_color_back)) + mdebug_hook (); +#endif /* HAVE_XFT2 */ + + hline = rface->hline; + if (hline) + { + if (hline->color) + info->gc[GC_HLINE] = get_gc (frame, hline->color, 1, NULL); + else + info->gc[GC_HLINE] = info->gc[GC_NORMAL]; + } + + box = rface->box; + if (box) + { + if (box->color_top) + info->gc[GC_BOX_TOP] = get_gc (frame, box->color_top, 1, NULL); + else + info->gc[GC_BOX_TOP] = info->gc[GC_NORMAL]; + + if (box->color_left && box->color_left != box->color_top) + info->gc[GC_BOX_LEFT] = get_gc (frame, box->color_left, 1, NULL); + else + info->gc[GC_BOX_LEFT] = info->gc[GC_BOX_TOP]; + + if (box->color_bottom && box->color_bottom != box->color_top) + info->gc[GC_BOX_BOTTOM] = get_gc (frame, box->color_bottom, 1, NULL); + else + info->gc[GC_BOX_BOTTOM] = info->gc[GC_BOX_TOP]; + + if (box->color_right && box->color_right != box->color_bottom) + info->gc[GC_BOX_RIGHT] = get_gc (frame, box->color_right, 1, NULL); + else + info->gc[GC_BOX_RIGHT] = info->gc[GC_BOX_BOTTOM]; + } + + rface->info = info; +} + + +static void +mwin__free_realized_face (MRealizedFace *rface) +{ + if (rface == rface->ascii_rface) + free (rface->info); +} + + +static void +mwin__fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface, + int reverse, + int x, int y, int width, int height, MDrawRegion region) +{ + GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_NORMAL : GC_INVERSE]; + + if (region) + gc = set_region (frame, gc, region); + + XFillRectangle (FRAME_DISPLAY (frame), (Window) win, gc, + x, y, width, height); +} + + +static void +mwin__draw_empty_boxes (MDrawWindow win, int x, int y, + MGlyphString *gstring, MGlyph *from, MGlyph *to, + int reverse, MDrawRegion region) +{ + MRealizedFace *rface = from->rface; + Display *display = FRAME_DISPLAY (rface->frame); + GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL]; + + if (from == to) + return; + + if (region) + gc = set_region (rface->frame, gc, region); + for (; from < to; from++) + { + XDrawRectangle (display, (Window) win, gc, + x, y - gstring->ascent + 1, from->g.xadv - 1, + gstring->ascent + gstring->descent - 2); + x += from->g.xadv; + } +} + + +static void +mwin__draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring, + MRealizedFace *rface, int reverse, + int x, int y, int width, MDrawRegion region) +{ + enum MFaceHLineType type = rface->hline->type; + GCInfo *info = rface->info; + GC gc = gc = info->gc[GC_HLINE]; + int i; + + y = (type == MFACE_HLINE_BOTTOM + ? y + gstring->text_descent - rface->hline->width + : type == MFACE_HLINE_UNDER + ? y + 1 + : type == MFACE_HLINE_STRIKE_THROUGH + ? y - ((gstring->ascent + gstring->descent) / 2) + : y - gstring->text_ascent); + if (region) + gc = set_region (frame, gc, region); + + for (i = 0; i < rface->hline->width; i++) + XDrawLine (FRAME_DISPLAY (frame), (Window) win, gc, + x, y + i, x + width - 1, y + i); +} + + +static void +mwin__draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring, + MGlyph *g, int x, int y, int width, MDrawRegion region) +{ + Display *display = FRAME_DISPLAY (frame); + MRealizedFace *rface = g->rface; + MFaceBoxProp *box = rface->box; + GCInfo *info = rface->info; + GC gc_top, gc_left, gc_right, gc_btm; + int y0, y1; + int i; + + y0 = y - (gstring->text_ascent + + rface->box->inner_vmargin + rface->box->width); + y1 = y + (gstring->text_descent + + rface->box->inner_vmargin + rface->box->width - 1); + + gc_top = info->gc[GC_BOX_TOP]; + if (region) + gc_top = set_region (frame, gc_top, region); + if (info->gc[GC_BOX_TOP] == info->gc[GC_BOX_BOTTOM]) + gc_btm = gc_top; + else + gc_btm = info->gc[GC_BOX_BOTTOM]; + + if (g->type == GLYPH_BOX) + { + int x0, x1; + + if (g->left_padding) + x0 = x + box->outer_hmargin, x1 = x + g->g.xadv - 1; + else + x0 = x, x1 = x + g->g.xadv - box->outer_hmargin - 1; + + /* Draw the top side. */ + for (i = 0; i < box->width; i++) + XDrawLine (display, (Window) win, gc_top, x0, y0 + i, x1, y0 + i); + + /* Draw the bottom side. */ + if (region && gc_btm != gc_top) + gc_btm = set_region (frame, gc_btm, region); + for (i = 0; i < box->width; i++) + XDrawLine (display, (Window) win, gc_btm, x0, y1 - i, x1, y1 - i); + + if (g->left_padding > 0) + { + /* Draw the left side. */ + if (info->gc[GC_BOX_LEFT] == info->gc[GC_BOX_TOP]) + gc_left = gc_top; + else + { + gc_left = info->gc[GC_BOX_LEFT]; + if (region) + gc_left = set_region (frame, gc_left, region); + } + for (i = 0; i < rface->box->width; i++) + XDrawLine (display, (Window) win, gc_left, + x0 + i, y0 + i, x0 + i, y1 - i); + } + else + { + /* Draw the right side. */ + if (info->gc[GC_BOX_RIGHT] == info->gc[GC_BOX_TOP]) + gc_right = gc_top; + else + { + gc_right = info->gc[GC_BOX_RIGHT]; + if (region) + gc_right = set_region (frame, gc_right, region); + } + for (i = 0; i < rface->box->width; i++) + XDrawLine (display, (Window) win, gc_right, + x1 - i, y0 + i, x1 - i, y1 - i); + } + } + else + { + /* Draw the top side. */ + for (i = 0; i < box->width; i++) + XDrawLine (display, (Window) win, gc_top, + x, y0 + i, x + width - 1, y0 + i); + + /* Draw the bottom side. */ + if (region && gc_btm != gc_top) + gc_btm = set_region (frame, gc_btm, region); + for (i = 0; i < box->width; i++) + XDrawLine (display, (Window) win, gc_btm, + x, y1 - i, x + width - 1, y1 - i); + } +} + + +#if 0 +static void +mwin__draw_bitmap (MFrame *frame, MDrawWindow win, MRealizedFace *rface, + int reverse, int x, int y, + int width, int height, int row_bytes, unsigned char *bmp, + MDrawRegion region) +{ + Display *display = FRAME_DISPLAY (frame); + int i, j; + GC gc = ((GCInfo *) rface->info)->gc[reverse ? GC_INVERSE : GC_NORMAL]; + + if (region) + gc = set_region (frame, gc, region); + + for (i = 0; i < height; i++, bmp += row_bytes) + for (j = 0; j < width; j++) + if (bmp[j / 8] & (1 << (7 - (j % 8)))) + XDrawPoint (display, (Window) win, gc, x + j, y + i); +} +#endif + +static void +mwin__draw_points (MFrame *frame, MDrawWindow win, MRealizedFace *rface, + int intensity, MDrawPoint *points, int num, + MDrawRegion region) +{ + GCInfo *info = rface->info; + GC gc; + + if (! (gc = info->gc[intensity])) + gc = info->gc[intensity] = get_gc_for_anti_alias (FRAME_DEVICE (frame), + info, intensity); + if (region) + gc = set_region (frame, gc, region); + + XDrawPoints (FRAME_DISPLAY (frame), (Window) win, gc, + (XPoint *) points, num, CoordModeOrigin); +} + + +static MDrawRegion +mwin__region_from_rect (MDrawMetric *rect) +{ + MDrawRegion region1 = XCreateRegion (); + MDrawRegion region2 = XCreateRegion (); + XRectangle xrect; + + xrect.x = rect->x; + xrect.y = rect->y; + xrect.width = rect->width; + xrect.height = rect->height; + XUnionRectWithRegion (&xrect, region1, region2); + XDestroyRegion (region1); + return region2; +} + +static void +mwin__union_rect_with_region (MDrawRegion region, MDrawMetric *rect) +{ + MDrawRegion region1 = XCreateRegion (); + XRectangle xrect; + + xrect.x = rect->x; + xrect.y = rect->y; + xrect.width = rect->width; + xrect.height = rect->height; + + XUnionRegion (region, region, region1); + XUnionRectWithRegion (&xrect, region1, region); + XDestroyRegion (region1); +} + +static void +mwin__intersect_region (MDrawRegion region1, MDrawRegion region2) +{ + MDrawRegion region = XCreateRegion (); + + XUnionRegion (region1, region1, region); + XIntersectRegion (region, region2, region1); + XDestroyRegion (region); +} + +static void +mwin__region_add_rect (MDrawRegion region, MDrawMetric *rect) +{ + MDrawRegion region1 = XCreateRegion (); + XRectangle xrect; + + xrect.x = rect->x; + xrect.y = rect->y; + xrect.width = rect->width; + xrect.height = rect->height; + XUnionRectWithRegion (&xrect, region1, region); + XDestroyRegion (region1); +} + +static void +mwin__region_to_rect (MDrawRegion region, MDrawMetric *rect) +{ + XRectangle xrect; + + XClipBox (region, &xrect); + rect->x = xrect.x; + rect->y = xrect.y; + rect->width = xrect.width; + rect->height = xrect.height; +} + +static void +mwin__free_region (MDrawRegion region) +{ + XDestroyRegion (region); +} + +static void +mwin__dump_region (MDrawRegion region) +{ + XRectangle rect; + XClipBox (region, &rect); + fprintf (mdebug__output, "(%d %d %d %d)\n", rect.x, rect.y, rect.width, rect.height); +} + + +static MDrawWindow +mwin__create_window (MFrame *frame, MDrawWindow parent) +{ + Display *display = FRAME_DISPLAY (frame); + Window win; + XWMHints wm_hints = { InputHint, False }; + XClassHint class_hints = { "M17N-IM", "m17n-im" }; + XSetWindowAttributes set_attrs; + unsigned long mask; + XGCValues values; + GCInfo *info = frame->rface->info; + + if (! parent) + parent = (MDrawWindow) RootWindow (display, FRAME_SCREEN (frame)); + mask = GCForeground; + XGetGCValues (display, info->gc[GC_INVERSE], mask, &values); + set_attrs.background_pixel = values.foreground; + set_attrs.backing_store = Always; + set_attrs.override_redirect = True; + set_attrs.save_under = True; + mask = CWBackPixel | CWBackingStore | CWOverrideRedirect | CWSaveUnder; + win = XCreateWindow (display, (Window) parent, 0, 0, 1, 1, 0, + CopyFromParent, InputOutput, CopyFromParent, + mask, &set_attrs); + XSetWMProperties (display, (Window) win, NULL, NULL, NULL, 0, + NULL, &wm_hints, &class_hints); + XSelectInput (display, (Window) win, StructureNotifyMask | ExposureMask); + return (MDrawWindow) win; +} + +static void +mwin__destroy_window (MFrame *frame, MDrawWindow win) +{ +#ifdef HAVE_XFT2 + XftDraw *xft_draw = FRAME_DEVICE (frame)->xft_draw; + + if (XftDrawDrawable (xft_draw) == (Drawable) win) + XftDrawChange (xft_draw, FRAME_DEVICE (frame)->drawable); +#endif /* HAVE_XFT2 */ + XDestroyWindow (FRAME_DISPLAY (frame), (Window) win); +} + +#if 0 +static MDrawWindow +mwin__event_window (void *event) +{ + return ((MDrawWindow) ((XEvent *) event)->xany.window); +} + +static void +mwin__print_event (void *arg, char *win_name) +{ + char *event_name; + XEvent *event = (XEvent *) arg; + + switch (event->xany.type) + { + case 2: event_name = "KeyPress"; break; + case 3: event_name = "KeyRelease"; break; + case 4: event_name = "ButtonPress"; break; + case 5: event_name = "ButtonRelease"; break; + case 6: event_name = "MotionNotify"; break; + case 7: event_name = "EnterNotify"; break; + case 8: event_name = "LeaveNotify"; break; + case 9: event_name = "FocusIn"; break; + case 10: event_name = "FocusOut"; break; + case 11: event_name = "KeymapNotify"; break; + case 12: event_name = "Expose"; break; + case 13: event_name = "GraphicsExpose"; break; + case 14: event_name = "NoExpose"; break; + case 15: event_name = "VisibilityNotify"; break; + case 16: event_name = "CreateNotify"; break; + case 17: event_name = "DestroyNotify"; break; + case 18: event_name = "UnmapNotify"; break; + case 19: event_name = "MapNotify"; break; + case 20: event_name = "MapRequest"; break; + case 21: event_name = "ReparentNotify"; break; + case 22: event_name = "ConfigureNotify"; break; + case 23: event_name = "ConfigureRequest"; break; + case 24: event_name = "GravityNotify"; break; + case 25: event_name = "ResizeRequest"; break; + case 26: event_name = "CirculateNotify"; break; + case 27: event_name = "CirculateRequest"; break; + case 28: event_name = "PropertyNotify"; break; + case 29: event_name = "SelectionClear"; break; + case 30: event_name = "SelectionRequest"; break; + case 31: event_name = "SelectionNotify"; break; + case 32: event_name = "ColormapNotify"; break; + case 33: event_name = "ClientMessage"; break; + case 34: event_name = "MappingNotify"; break; + default: event_name = "unknown"; + } + + fprintf (mdebug__output, "%s: %s\n", win_name, event_name); +} +#endif + +static void +mwin__map_window (MFrame *frame, MDrawWindow win) +{ + XMapRaised (FRAME_DISPLAY (frame), (Window) win); +} + +static void +mwin__unmap_window (MFrame *frame, MDrawWindow win) +{ + XUnmapWindow (FRAME_DISPLAY (frame), (Window) win); +} + +static void +mwin__window_geometry (MFrame *frame, MDrawWindow win, MDrawWindow parent_win, + MDrawMetric *geometry) +{ + Display *display = FRAME_DISPLAY (frame); + XWindowAttributes attr; + Window parent = (Window) parent_win, root; + + XGetWindowAttributes (display, (Window) win, &attr); + geometry->x = attr.x + attr.border_width; + geometry->y = attr.y + attr.border_width; + geometry->width = attr.width; + geometry->height = attr.height; + + if (! parent) + parent = RootWindow (display, FRAME_SCREEN (frame)); + while (1) + { + Window this_parent, *children; + unsigned n; + + XQueryTree (display, (Window) win, &root, &this_parent, &children, &n); + if (children) + XFree (children); + if (this_parent == parent || this_parent == root) + break; + win = (MDrawWindow) this_parent; + XGetWindowAttributes (display, (Window) win, &attr); + geometry->x += attr.x + attr.border_width; + geometry->y += attr.y + attr.border_width; + } +} + +static void +mwin__adjust_window (MFrame *frame, MDrawWindow win, + MDrawMetric *current, MDrawMetric *new) +{ + Display *display = FRAME_DISPLAY (frame); + unsigned int mask = 0; + XWindowChanges values; + + if (current->width != new->width) + { + mask |= CWWidth; + if (new->width <= 0) + new->width = 1; + values.width = current->width = new->width; + } + if (current->height != new->height) + { + mask |= CWHeight; + if (new->height <= 0) + new->height = 1; + values.height = current->height = new->height; + } + if (current->x != new->x) + { + mask |= CWX; + values.x = current->x = new->x; + } + if (current->y != new->y) + { + mask |= CWY; + current->y = new->y; + values.y = current->y = new->y; + } + if (mask) + XConfigureWindow (display, (Window) win, mask, &values); + XClearWindow (display, (Window) win); +} + +static MSymbol +mwin__parse_event (MFrame *frame, void *arg, int *modifiers) +{ + XEvent *event = (XEvent *) arg; + MDisplayInfo *disp_info = FRAME_DEVICE (frame)->display_info; + int len; + char buf[512]; + KeySym keysym; + MSymbol key; + + *modifiers = 0; + if (event->xany.type != KeyPress + /* && event->xany.type != KeyRelease */ + ) + return Mnil; + len = XLookupString ((XKeyEvent *) event, (char *) buf, 512, &keysym, NULL); + if (len > 1) + return Mnil; + if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R) + return Mnil; +#ifdef XK_XKB_KEYS + if ((keysym & 0xff00) == 0xfe00) + return Mnil; +#endif + if (len == 1 && keysym >= XK_space && keysym <= XK_asciitilde) + { + int c = keysym; + + key = minput__char_to_key (c); + if (c == ' ' && ((XKeyEvent *) event)->state & ShiftMask) + *modifiers |= MINPUT_KEY_SHIFT_MODIFIER; + } + else + { + char *str = XKeysymToString (keysym); + + if (! str) + return Mnil; + key = msymbol (str); + if (((XKeyEvent *) event)->state & ShiftMask) + *modifiers |= MINPUT_KEY_SHIFT_MODIFIER; + } + if (((XKeyEvent *) event)->state & ControlMask) + *modifiers |= MINPUT_KEY_CONTROL_MODIFIER; + if (((XKeyEvent *) event)->state & disp_info->meta_mask) + *modifiers |= MINPUT_KEY_META_MODIFIER; + if (((XKeyEvent *) event)->state & disp_info->alt_mask) + *modifiers |= MINPUT_KEY_ALT_MODIFIER; + if (((XKeyEvent *) event)->state & disp_info->super_mask) + *modifiers |= MINPUT_KEY_SUPER_MODIFIER; + if (((XKeyEvent *) event)->state & disp_info->hyper_mask) + *modifiers |= MINPUT_KEY_HYPER_MODIFIER; +#ifdef XK_XKB_KEYS + if (((XKeyEvent *) event)->state & disp_info->altgr_mask) + *modifiers |= MINPUT_KEY_ALTGR_MODIFIER; +#endif + return key; +} + + +void +mwin__dump_gc (MFrame *frame, MRealizedFace *rface) +{ + unsigned long valuemask = GCForeground | GCBackground | GCClipMask; + XGCValues values; + Display *display = FRAME_DISPLAY (frame); + GCInfo *info = rface->info; + int i; + + for (i = 0; i <= GC_INVERSE; i++) + { + XGetGCValues (display, info->gc[i], valuemask, &values); + fprintf (mdebug__output, "GC%d: fore/#%lX back/#%lX", i, + values.foreground, values.background); + fprintf (mdebug__output, "\n"); + } +} + +static MDeviceDriver x_driver = + { + mwin__close_device, + mwin__device_get_prop, + mwin__realize_face, + mwin__free_realized_face, + mwin__fill_space, + mwin__draw_empty_boxes, + mwin__draw_hline, + mwin__draw_box, + mwin__draw_points, + mwin__region_from_rect, + mwin__union_rect_with_region, + mwin__intersect_region, + mwin__region_add_rect, + mwin__region_to_rect, + mwin__free_region, + mwin__dump_region, + mwin__create_window, + mwin__destroy_window, + mwin__map_window, + mwin__unmap_window, + mwin__window_geometry, + mwin__adjust_window, + mwin__parse_event + }; + +/* Functions to be stored in MDeviceLibraryInterface by dlsym (). */ + +int +device_init () +{ + M_iso8859_1 = msymbol ("iso8859-1"); + M_iso10646_1 = msymbol ("iso10646-1"); + + display_info_list = mplist (); + device_list = mplist (); + +#ifdef HAVE_XFT2 + xft_driver.select = mfont__ft_driver.select; + xft_driver.list = mfont__ft_driver.list; + xft_driver.list_family_names = mfont__ft_driver.list_family_names; +#endif + + Mxim = msymbol ("xim"); + msymbol_put (Mxim, Minput_driver, &minput_xim_driver); + + return 0; +} + +int +device_fini () +{ + M17N_OBJECT_UNREF (display_info_list); + M17N_OBJECT_UNREF (device_list); + return 0; +} + + +#ifdef X_SET_ERROR_HANDLER +static int +x_error_handler (Display *display, XErrorEvent *error) +{ + mdebug_hook (); + return 0; +} + +static int +x_io_error_handler (Display *display) +{ + mdebug_hook (); + return 0; +} +#endif + +/** Return an MWDevice object corresponding to a display specified in + PLIST. + + It searches device_list for a device matching the display. If + found, return the found object. Otherwise, return a newly created + object. */ + +int +device_open (MFrame *frame, MPlist *param) +{ + Display *display = NULL; + Screen *screen = NULL; + int screen_num; + Drawable drawable = 0; + Widget widget = NULL; + Colormap cmap = 0; + int auto_display = 0; + MDisplayInfo *disp_info = NULL; + MWDevice *device = NULL; + MSymbol key; + XWindowAttributes attr; + unsigned depth = 0; + MPlist *plist; + AppData app_data; + MFont *font = NULL; + MFace *face; + int use_xfont = 0, use_freetype = 0, use_xft = 0; + + for (plist = param; (key = mplist_key (plist)) != Mnil; + plist = mplist_next (plist)) + { + if (key == Mdisplay) + display = (Display *) mplist_value (plist); + else if (key == Mscreen) + screen = mplist_value (plist); + else if (key == Mdrawable) + drawable = (Drawable) mplist_value (plist); + else if (key == Mdepth) + depth = (unsigned) mplist_value (plist); + else if (key == Mwidget) + widget = (Widget) mplist_value (plist); + else if (key == Mcolormap) + cmap = (Colormap) mplist_value (plist); + else if (key == Mfont) + { + MSymbol val = MPLIST_SYMBOL (plist); + + if (val == Mx) + use_xfont = 1; +#ifdef HAVE_FREETYPE + else if (val == Mfreetype) + use_freetype = 1; +#ifdef HAVE_XFT2 + else if (val == Mxft) + use_xft = 1; +#endif +#endif + } + } + + /* If none of them is specified, use all of them. */ + if (! use_xfont && ! use_freetype && ! use_xft) + use_xfont = use_freetype = use_xft = 1; + + if (widget) + { + display = XtDisplay (widget); + screen_num = XScreenNumberOfScreen (XtScreen (widget)); + depth = DefaultDepth (display, screen_num); + } + else if (drawable) + { + Window root_window; + int x, y; + unsigned width, height, border_width; + + if (! display) + MERROR (MERROR_WIN, -1); + XGetGeometry (display, drawable, &root_window, + &x, &y, &width, &height, &border_width, &depth); + XGetWindowAttributes (display, root_window, &attr); + screen_num = XScreenNumberOfScreen (attr.screen); + } + else + { + if (screen) + display = DisplayOfScreen (screen); + else + { + if (! display) + { + display = XOpenDisplay (NULL); + if (! display) + MERROR (MERROR_WIN, -1); + auto_display = 1; + } + screen = DefaultScreenOfDisplay (display); + } + screen_num = XScreenNumberOfScreen (screen); + if (! depth) + depth = DefaultDepth (display, screen_num); + } + + if (! cmap) + cmap = DefaultColormap (display, screen_num); + + for (plist = display_info_list; mplist_key (plist) != Mnil; + plist = mplist_next (plist)) + { + disp_info = (MDisplayInfo *) mplist_value (plist); + if (disp_info->display == display) + break; + } + + if (mplist_key (plist) != Mnil) + M17N_OBJECT_REF (disp_info); + else + { + M17N_OBJECT (disp_info, free_display_info, MERROR_WIN); + disp_info->display = display; + disp_info->auto_display = auto_display; + disp_info->font_list = mplist (); + find_modifier_bits (disp_info); + disp_info->MULE_BASELINE_OFFSET + = XInternAtom (display, "_MULE_BASELINE_OFFSET", False); + disp_info->AVERAGE_WIDTH + = XInternAtom (display, "AVERAGE_WIDTH", False); + mplist_add (display_info_list, Mt, disp_info); + } + + for (plist = device_list; mplist_key (plist) != Mnil; + plist = mplist_next (plist)) + { + device = (MWDevice *) mplist_value (plist); + if (device->display_info == disp_info + && device->depth == depth + && device->cmap == cmap + && device->screen_num == screen_num) + break; + } + + if (mplist_key (plist) != Mnil) + M17N_OBJECT_REF (device); + else + { + unsigned long valuemask = GCForeground; + XGCValues values; + double pixels, mm; + + M17N_OBJECT (device, free_device, MERROR_WIN); + device->display_info = disp_info; + device->screen_num = screen_num; + /* A drawable on which to create GCs. */ + device->drawable = XCreatePixmap (display, + RootWindow (display, screen_num), + 1, 1, depth); + device->depth = depth; + device->cmap = cmap; + pixels = DisplayHeight (display, screen_num); + mm = DisplayHeightMM (display, screen_num); + device->resy = (mm < 1) ? 100 : pixels * 25.4 / mm; + device->realized_face_list = mplist (); + device->realized_font_list = mplist (); + mplist_add (device->realized_font_list, Mt, NULL); + device->realized_fontset_list = mplist (); + device->gc_list = mplist (); + values.foreground = BlackPixel (display, screen_num); + device->scratch_gc = XCreateGC (display, device->drawable, + valuemask, &values); +#ifdef HAVE_XFT2 + device->xft_draw = XftDrawCreate (display, device->drawable, + DefaultVisual (display, screen_num), + cmap); +#endif + } + + frame->device = device; + frame->device_type = MDEVICE_SUPPORT_OUTPUT | MDEVICE_SUPPORT_INPUT; + frame->dpi = device->resy; + frame->driver = &x_driver; + frame->font_driver_list = mplist (); +#ifdef HAVE_XFT2 + if (use_xft) + { + mplist_add (frame->font_driver_list, Mfreetype, &xft_driver); + use_freetype = 0; + } +#endif /* HAVE_XFT2 */ +#ifdef HAVE_FREETYPE + if (use_freetype) + mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver); +#endif /* HAVE_FREETYPE */ + if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list)) + mplist_add (frame->font_driver_list, Mx, &xfont_driver); + + frame->realized_font_list = device->realized_font_list; + frame->realized_face_list = device->realized_face_list; + frame->realized_fontset_list = device->realized_fontset_list; + + if (widget) + { + XtResource resources[] = { + { XtNfont, XtCFont, XtRString, sizeof (String), + XtOffset (AppDataPtr, font), XtRString, DEFAULT_FONT }, + { XtNforeground, XtCForeground, XtRString, sizeof (String), + XtOffset (AppDataPtr, foreground), XtRString, "black" }, + { XtNbackground, XtCBackground, XtRString, sizeof (String), + XtOffset (AppDataPtr, background), XtRString, "white" }, + { XtNreverseVideo, XtCReverseVideo, XtRBoolean, sizeof (Boolean), + XtOffset (AppDataPtr, reverse_video), XtRImmediate, (caddr_t) FALSE } + }; + + XtGetApplicationResources (widget, &app_data, + resources, XtNumber (resources), NULL, 0); + frame->foreground = msymbol (app_data.foreground); + frame->background = msymbol (app_data.background); + frame->videomode = app_data.reverse_video == True ? Mreverse : Mnormal; + } + else + { + app_data.font = DEFAULT_FONT; + frame->foreground = msymbol ("black"); + frame->background = msymbol ("white"); + frame->videomode = Mnormal; + } + + if (strcmp (app_data.font, DEFAULT_FONT) != 0) + { + XFontStruct *xfont = XLoadQueryFont (display, app_data.font); + unsigned long value; + char *name; + + if (xfont) + { + font = mfont_parse_name (app_data.font, Mx); + if (! font + && XGetFontProperty (xfont, XA_FONT, &value) + && (name = ((char *) XGetAtomName (display, (Atom) value)))) + font = mfont_parse_name (name, Mx); + XFreeFont (display, xfont); + } + } + if (! font) + font = mfont_parse_name (DEFAULT_FONT, Mx); + else if (! font->size) + font->size = 130; + face = mface_from_font (font); + free (font); + face->property[MFACE_FONTSET] = mfontset (NULL); + face->property[MFACE_FOREGROUND] = frame->foreground; + face->property[MFACE_BACKGROUND] = frame->background; + mface_put_prop (face, Mhline, mface_get_prop (mface__default, Mhline)); + mface_put_prop (face, Mbox, mface_get_prop (mface__default, Mbox)); + face->property[MFACE_VIDEOMODE] = frame->videomode; + mface_put_prop (face, Mhook_func, + mface_get_prop (mface__default, Mhook_func)); + face->property[MFACE_RATIO] = (void *) 100; + mplist_push (param, Mface, face); + M17N_OBJECT_UNREF (face); + +#ifdef X_SET_ERROR_HANDLER + XSetErrorHandler (x_error_handler); + XSetIOErrorHandler (x_io_error_handler); +#endif + return 0; +} + + + +/* XIM (X Input Method) handler */ + +typedef struct MInputXIMMethodInfo +{ + Display *display; + XIM xim; + MSymbol language; + MSymbol coding; +} MInputXIMMethodInfo; + +typedef struct MInputXIMContextInfo +{ + XIC xic; + Window win; + MConverter *converter; +} MInputXIMContextInfo; + +static int +xim_open_im (MInputMethod *im) +{ + MInputXIMArgIM *arg = (MInputXIMArgIM *) im->arg; + MLocale *saved, *this; + char *save_modifier_list; + XIM xim; + MInputXIMMethodInfo *im_info; + + saved = mlocale_set (LC_CTYPE, NULL); + this = mlocale_set (LC_CTYPE, arg->locale ? arg->locale : ""); + if (! this) + /* The specified locale is not supported. */ + MERROR (MERROR_LOCALE, -1); + if (mlocale_get_prop (this, Mcoding) == Mnil) + { + /* Unable to decode the output of XIM. */ + mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname))); + MERROR (MERROR_LOCALE, -1); + } + + if (arg->modifier_list) + save_modifier_list = XSetLocaleModifiers (arg->modifier_list); + else + save_modifier_list = XSetLocaleModifiers (""); + if (! save_modifier_list) + { + /* The specified locale is not supported by X. */ + mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname))); + MERROR (MERROR_LOCALE, -1); + } + + xim = XOpenIM (arg->display, arg->db, arg->res_name, arg->res_class); + if (! xim) + { + /* No input method is available in the current locale. */ + XSetLocaleModifiers (save_modifier_list); + mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname))); + MERROR (MERROR_WIN, -1); + } + + MSTRUCT_MALLOC (im_info, MERROR_WIN); + im_info->display = arg->display; + im_info->xim = xim; + im_info->language = mlocale_get_prop (this, Mlanguage); + im_info->coding = mlocale_get_prop (this, Mcoding); + im->info = im_info; + + XSetLocaleModifiers (save_modifier_list); + mlocale_set (LC_CTYPE, msymbol_name (mlocale_get_prop (saved, Mname))); + + return 0; +} + +static void +xim_close_im (MInputMethod *im) +{ + MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) im->info; + + XCloseIM (im_info->xim); + free (im_info); +} + +static int +xim_create_ic (MInputContext *ic) +{ + MInputXIMArgIC *arg = (MInputXIMArgIC *) ic->arg; + MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info; + MInputXIMContextInfo *ic_info; + XIC xic; + + if (! arg->input_style) + { + /* By default, use Root style. */ + arg->input_style = XIMPreeditNothing | XIMStatusNothing; + arg->preedit_attrs = NULL; + arg->status_attrs = NULL; + } + + if (! arg->preedit_attrs && ! arg->status_attrs) + xic = XCreateIC (im_info->xim, + XNInputStyle, arg->input_style, + XNClientWindow, arg->client_win, + XNFocusWindow, arg->focus_win, + NULL); + else if (arg->preedit_attrs && ! arg->status_attrs) + xic = XCreateIC (im_info->xim, + XNInputStyle, arg->input_style, + XNClientWindow, arg->client_win, + XNFocusWindow, arg->focus_win, + XNPreeditAttributes, arg->preedit_attrs, + NULL); + else if (! arg->preedit_attrs && arg->status_attrs) + xic = XCreateIC (im_info->xim, + XNInputStyle, arg->input_style, + XNClientWindow, arg->client_win, + XNFocusWindow, arg->focus_win, + XNStatusAttributes, arg->status_attrs, + NULL); + else + xic = XCreateIC (im_info->xim, + XNInputStyle, arg->input_style, + XNClientWindow, arg->client_win, + XNFocusWindow, arg->focus_win, + XNPreeditAttributes, arg->preedit_attrs, + XNStatusAttributes, arg->status_attrs, + NULL); + if (! xic) + MERROR (MERROR_WIN, -1); + + MSTRUCT_MALLOC (ic_info, MERROR_WIN); + ic_info->xic = xic; + ic_info->win = arg->focus_win; + ic_info->converter = mconv_buffer_converter (im_info->coding, NULL, 0); + ic->info = ic_info; + return 0; +} + +static void +xim_destroy_ic (MInputContext *ic) +{ + MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info; + + XDestroyIC (ic_info->xic); + mconv_free_converter (ic_info->converter); + free (ic_info); + ic->info = NULL; +} + +static int +xim_filter (MInputContext *ic, MSymbol key, void *event) +{ + MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info; + + return (XFilterEvent ((XEvent *) event, ic_info->win) == True); +} + + +static int +xim_lookup (MInputContext *ic, MSymbol key, void *arg, MText *mt) +{ + MInputXIMMethodInfo *im_info = (MInputXIMMethodInfo *) ic->im->info; + MInputXIMContextInfo *ic_info = (MInputXIMContextInfo *) ic->info; + XKeyPressedEvent *ev = (XKeyPressedEvent *) arg; + KeySym keysym; + Status status; + char *buf; + int len; + + buf = (char *) alloca (512); + len = XmbLookupString (ic_info->xic, ev, buf, 512, &keysym, &status); + if (status == XBufferOverflow) + { + buf = (char *) alloca (len); + len = XmbLookupString (ic_info->xic, ev, buf, len, &keysym, &status); + } + + mtext_reset (ic->produced); + if (len == 0) + return 1; + + mconv_reset_converter (ic_info->converter); + mconv_rebind_buffer (ic_info->converter, (unsigned char *) buf, len); + mconv_decode (ic_info->converter, ic->produced); + mtext_put_prop (ic->produced, 0, mtext_nchars (ic->produced), + Mlanguage, (void *) im_info->language); + mtext_cpy (mt, ic->produced); + mtext_reset (ic->produced); + return 0; +} + + +/*=*/ + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + +/* External API */ + +/*** @addtogroup m17nInputMethodWin */ + +/*** @{ */ +/*=*/ +/***en + @brief Input method driver for XIM. + + The driver #minput_xim_driver is for the foreign input method of + name #Mxim. It uses XIM (X Input Methods) as a background input + engine. + + As the symbol #Mxim has property #Minput_driver whose value is + a pointer to this driver, the input method of language #Mnil + and name #Mxim uses this driver. + + Therefore, for such input methods, the driver dependent arguments + to the functions whose name begin with minput_ must be as follows. + + The argument $ARG of the function minput_open_im () must be a + pointer to the structure #MInputXIMArgIM. See the documentation + of #MInputXIMArgIM for more details. + + The argument $ARG of the function minput_create_ic () must be a + pointer to the structure #MInputXIMArgIC. See the documentation + of #MInputXIMArgIC for more details. + + The argument $ARG of the function minput_filter () must be a + pointer to the structure @c XEvent. The argument $KEY is ignored. + + The argument $ARG of the function minput_lookup () must be the + same one as that of the function minput_filter (). The argument + $KEY is ignored. */ + +/***ja + @brief XIM�����ϥɥ饤��. + + �ɥ饤�� #minput_xim_driver �� #Mxim ��̾���Ȥ��ƻ��ij������ϥ᥽�å��ѤǤ��ꡢ + XIM (X Input Methods) ��Хå����饦��ɤ����ϥ��󥸥�Ȥ��ƻ��Ѥ��롣 + + ����ܥ� #Mxim �Ϥ��Υɥ饤�ФؤΥݥ��󥿤��ͤȤ���ץ��ѥƥ� + #Minput_driver �������LANGUAGE �� #Mnil ��̾���� #Mxim + �Ǥ������ϥ᥽�åɤϤ��Υɥ饤�Ф����Ѥ��롣 + + �������äơ����������ϥ᥽�åɤǤϡ�minput_ + �ǻϤޤ�̾������Ĵؿ��Υɥ饤�Ф˰�¸��������ϼ��Τ褦�ʤ�ΤǤʤ��ƤϤʤ�ʤ��� + + �ؿ� minput_open_im () �ΰ��� $ARG �Ϲ�¤�� #MInputXIMArgIM + �ؤΥݥ��󥿤Ǥʤ��ƤϤʤ�ʤ����ܺ٤ˤĤ��Ƥ� #MInputXIMArgIM �������򻲾ȡ� + + �ؿ� minput_create_ic () �ΰ��� $ARG �Ϲ�¤�� #MInputXIMArgIC + �ؤΥݥ��󥿤Ǥʤ��ƤϤʤ�ʤ����ܺ٤ˤĤ��Ƥ� #MInputXIMArgIC �������򻲾ȡ� + + �ؿ� minput_filter () �ΰ��� $ARG �Ϲ�¤�� @c XEvent + �ؤΥݥ��󥿤Ǥʤ��ƤϤʤ�ʤ������� $KEY ��̵�뤵��롣 + + �ؿ� minput_lookup () �ΰ��� $ARG �ϴؿ� function minput_filter () + �ΰ��� $ARG ��Ʊ����ΤǤʤ��ƤϤʤ�ʤ��� ���� $KEY �ϡ�̵�뤵��롣 */ + +MInputDriver minput_xim_driver = + { xim_open_im, xim_close_im, xim_create_ic, xim_destroy_ic, + xim_filter, xim_lookup, NULL }; +/*=*/ +/*** @} */ +/*=*/ +#else /* not HAVE_X11 */ + +int device_open () { return -1; } + +#endif /* not HAVE_X11 */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/m17n-X.h b/src/m17n-X.h new file mode 100644 index 0000000..86cb3b7 --- /dev/null +++ b/src/m17n-X.h @@ -0,0 +1,146 @@ +/* m17n-X.h -- header file for the GUI API on X Windows. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_X_H_ +#define _M17N_X_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* For inputting. */ + +extern MInputDriver minput_xim_driver; +extern MSymbol Mxim; + +/*** @ingroup m17nInputMethodWin */ +/***en + @brief Structure pointed to by the argument $ARG of the function minput_open_im (). + + The type #MInputXIMArgIM is the structure pointed to by the + argument $ARG of the function minput_open_im () for the foreign + input method of name #Mxim. */ + +/***ja + @brief �ؿ� minput_open_im () �ΰ��� $ARG �ˤ�äƻؤ���빽¤��. + + #MInputXIMArgIM ���ϡ��ؿ� minput_open_im () ��̾�� #Mxim + ����ij������ϥ᥽�åɤ���������ݤ˰��� $ARG �ˤ�äƻؤ���빽¤�ΤǤ��롣 */ + +typedef struct +{ + /***en The meaning of the following four members are the same as + arguments to XOpenIM (). */ + /***ja �ʲ��Σ��ĤΥ��Фΰ�̣�ϡ�XOpenIM () �ΰ����ΰ�̣��Ʊ���Ǥ���. */ + + /***en Display of the client. */ + /***ja ���饤����ȤΥǥ����ץ쥤. */ + Display *display; + + /***en Pointer to the X resource database. */ + /***ja X �꥽�������ǡ����١����ؤΥݥ���. */ + XrmDatabase db; + + /***en Full class name of the application. */ + /***ja ���ץꥱ�������δ����ʥ��饹̾. */ + char *res_class; + + /***en Full resource name of the application. */ + /***ja ���ץꥱ�������δ����ʥ꥽����̾. */ + char *res_name; + + /***en Locale name under which an XIM is opened. */ + /***ja XIM�������ץ󤵤줿��������̾. */ + char *locale; + + /***en Arguments to XSetLocaleModifiers (). */ + /***ja XSetLocaleModifiers () �ΰ���. */ + char *modifier_list; +} MInputXIMArgIM; + +/*=*/ + +/*** @ingroup m17nInputMethodWin */ +/***en + @brief Structure pointed to by the argument $ARG of the function minput_create_ic (). + + The type #MInputXIMArgIC is the structure pointed to by the + argument $ARG of the function minput_create_ic () for the foreign + input method of name #Mxim. */ + +/***ja + @brief �ؿ� minput_create_ic () �ΰ��� $ARG �ˤ�äƻؤ���빽¤��. + + #MInputXIMArgIC ���ϡ��ؿ� minput_create_ic () ��̾�� #Mxim + ����ij������ϥ᥽�å��Ѥ˸ƤФ��ݤˡ����� $ARG �ˤ�äƻؤ���빽¤�ΤǤ��롣 */ + +typedef struct +{ + /***en Used as the arguments of @c XCreateIC following @c + XNInputStyle. If this is zero, ( @c XIMPreeditNothing | @c + XIMStatusNothing) is used, and \ and + \ are set to @c NULL. */ + /***ja @c XCreateIC �� @c XNInputStyle ��³�������Ȥ����Ѥ����롣 + �����ʤ�С� ( @c XIMPreeditNothing | @c XIMStatusNothing) ���� + ����졢 \ �� \ �� @c NULL + �����ꤵ��롣 */ + + XIMStyle input_style; + /***en Used as the argument of @c XCreateIC following @c XNClientWindow. */ + /***ja @c XCreateIC �� @c XNClientWindow ��³�������Ȥ����Ѥ����롣 */ + + Window client_win; + /***en Used as the argument of @c XCreateIC following @c XNFocusWindow. */ + /***ja @c XCreateIC �� @c XNFocusWindow ��³�������Ȥ����Ѥ����롣 */ + + Window focus_win; + /***en If non- @c NULL, used as the argument of @c XCreateIC following + @c XNPreeditAttributes. */ + /***ja @c NULL �Ǥʤ���С� @c XCreateIC following ��@c + XNPreeditAttributes ��³�������Ȥ����Ѥ����롣 */ + + XVaNestedList preedit_attrs; + /***en If non- @c NULL, used as the argument of @c XCreateIC following + @c XNStatusAttributes. */ + /***ja @c NULL �Ǥʤ���С� @c XCreateIC following �� @c + XNStatusAttributes ��³�������Ȥ����Ѥ����롣 */ + + XVaNestedList status_attrs; +} MInputXIMArgIC; +/*=*/ + +#ifdef __cplusplus +} +#endif + +#endif /* not _M17N_X_H_ */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/m17n-core.c b/src/m17n-core.c new file mode 100644 index 0000000..fe5aa77 --- /dev/null +++ b/src/m17n-core.c @@ -0,0 +1,1204 @@ +/* m17n-core.c -- body of the CORE API. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nIntro + @brief Introduction to the m17n library. + + API LEVELS + + The API of the m17n library is divided into these five. + +
    +
  1. CORE API + + It provides basic modules to handle M-texts. To use this API, an + application program must include .h> and be + linked with -lm17n-core. + +
  2. SHELL API + + It provides modules for character properties, character set + handling, code conversion, etc. They load various kinds of + data from the database on demand. To use this API, an application + program must include .h> and be linked with + -lm17n-core -lm17n. + + When you use this API, CORE API is also available. + +
  3. FLT API + + It provides modules for text shaping using @ref mdbFLT. To use + this API, an application program must include .h> + and be linked with -lm17n-core -lm17n-flt. + + When you use this API, CORE API is also available. + +
  4. GUI API + + It provides GUI modules such as drawing and inputting M-texts on a + graphic device. This API itself is independent of graphic + devices, but most functions require an argument MFrame that is + created for a specific type of graphic devices. The currently + supported graphic devices are null device, the X Window System, + and image data (gdImagePtr) of the GD library. + + On a frame of a null device, you cannot draw text nor use input + methods. However, functions like mdraw_glyph_list (), etc. are + available. + + On a frame of the X Window System, you can use the whole GUI API. + + On a frame of the GD library, you can use all drawing API but + cannot use input methods. + + To use this API, an application program must include + .h> and be linked with -lm17n-core -lm17n + -lm17n-gui. + + When you use this API, CORE, SHELL, and FLT APIs are also + available. + +
  5. MISC API + + It provides miscellaneous functions to support error handling and + debugging. This API cannot be used standalone; it must be used + with one or more APIs listed above. To use this API, an + application program must include .h> in + addition to one of the header files described above. + +
+ + See also the section @ref m17n-config "m17n-config(1)". + + ENVIRONMENT VARIABLES + + The m17n library pays attention to the following environment + variables. + +
    +
  • @c M17NDIR + + The name of the directory that contains data of the m17n database. + See @ref m17nDatabase for details. + +
  • @c MDEBUG_XXX + + Environment variables whose names start with "MDEBUG_" control + debug information output. See @ref m17nDebug for details. + +
+ + API NAMING CONVENTION + + The m17n library exports functions, variables, macros, and types. + All of them start with the letter 'm' or 'M', and are followed by + an object name (e.g. "symbol", "plist") or a module name + (e.g. draw, input). Note that the name of M-text objects start + with "mtext" and not with "mmtext". + +
    + +
  • functions -- mobject () or mobject_xxx () + + They start with 'm' and are followed by an object name in lower + case. Words are separated by '_'. For example, msymbol (), + mtext_ref_char (), mdraw_text (). + +
  • non-symbol variables -- mobject, or mobject_xxx + + The naming convention is the same as functions (e.g. mface_large). + +
  • symbol variables -- Mname + + Variables of the type MSymbol start with 'M' and are followed by + their names. Words are separated by '_'. For example, Mlanguage + (the name is "language"), Miso_2022 (the name is "iso-2022"). + +
  • macros -- MOBJECT_XXX + + They start with 'M' and are followed by an object name in upper + case. Words are separated by '_'. + +
  • types -- MObject or MObjectXxx + + They start with 'M' and are followed by capitalized object names. + Words are concatenated directly and no '_' are used. For example, + MConverter, MInputDriver. + +
+ + */ + +/***ja + @addtogroup m17nIntro + @brief m17n �饤�֥�� ����ȥ����������. + + @em API�Υ�٥� + + m17n �饤�֥��� API �ϰʲ��Σ����ʬ�व��Ƥ��롣 + +
    +
  1. ���� API + + M-text �򰷤�����δ���Ū�ʥ⥸�塼����󶡤��롣 + ���� API �����Ѥ��뤿��ˤϡ����ץꥱ�������ץ������� + .h> �� include ���� -lm17n-core + �ǥ�󥯤���ʤ��ƤϤʤ�ʤ��� + +
  2. ������ API + + ʸ���ץ��ѥƥ���ʸ���������������Ѵ����Τ���Υ⥸�塼����󶡤��롣 + �����Υ⥸�塼��ϡ��ǡ����١�������ɬ�פ˱�����¿�ͤʥǡ���������ɤ��롣 + ���� API �����Ѥ��뤿��ˤϡ����ץꥱ�������ץ������� + .h> �� include ���� -lm17n-core -lm17n + �ǥ�󥯤���ʤ��ƤϤʤ�ʤ��� + + ���� API ����Ѥ���С����� API �⼫ưŪ�˻��Ѳ�ǽ�Ȥʤ롣 + +
  3. FLT API + + ʸ����ɽ���� @ref mdbFLT ���Ѥ���⥸�塼����󶡤��롣���� API + �����Ѥ��뤿��ˤϡ����ץꥱ�������ץ������� .h> + �� include ���� -lm17n-core -lm17n-flt �ǥ�󥯤���ʤ��ƤϤʤ�ʤ��� + + ���� API ����Ѥ���С����� API �⼫ưŪ�˻��Ѳ�ǽ�Ȥʤ롣 + +
  4. GUI API + + ����ե��å��ǥХ������ M-text ��ɽ�����������Ϥ����ꤹ�뤿��� + GUI �⥸�塼����󶡤��롣���� API + ���Τϥ���ե��å��ǥХ����Ȥ���Ω�Ǥ��뤬�� + ¿���δؿ�������Υ���ե��å��ǥХ����Ѥ˺������줿 + MFrame ������˼�롣 + �������ǥ��ݡ��Ȥ���Ƥ��륰��ե��å��ǥХ����ϡ��̥�ǥХ�����X + ������ɥ������ƥࡢ����� GD �饤�֥��Υ��᡼���ǡ��� + (gdImagePtr) �Ǥ��롣 + + �̥�ǥХ����Υե졼���Ǥ�ɽ�������Ϥ�Ǥ��ʤ��������� + mdraw_glyph_list () �ʤɤδؿ��ϻ��Ѳ�ǽ�Ǥ��롣 + + X ������ɥ������ƥ�Υե졼���ǤϤ��٤Ƥ� GUI API �����ѤǤ��롣 + + GD �饤�֥��Υե졼���Ǥϡ������Ѥ� API + �Ϥ��٤ƻ��ѤǤ��뤬�����ϤϤǤ��ʤ��� + + ���� API ����Ѥ��뤿��ˤϡ����ץꥱ�������ץ������� + .h> �� include ����-lm17n-core -lm17n -lm17n-gui + �ǥ�󥯤���ʤ��ƤϤʤ�ʤ��� + + ���� API ����Ѥ���С����� API�������� API������� FLT API + �⼫ưŪ�˻��Ѳ�ǽ�Ȥʤ롣 + +
  5. ����¾�� API + + ���顼�������ǥХå��ѤΤ���¾�δؿ����󶡤��롣���� API + �Ϥ�������Ǥϻ��ѤǤ������嵭��¾�� API + �ȶ��˻Ȥ������Ѥ��뤿��ˤϡ��嵭�Τ����줫��include + �ե�����˲ä��ơ� .h> ��include + ���ʤ��ƤϤʤ�ʤ��� + +
+ + @ref m17n-config "m17n-config(1)" ��⻲�ȡ� + + @em �Ķ��ѿ� + + m17n �饤�֥��ϰʲ��δĶ��ѿ��򻲾Ȥ��롣 + +
    +
  • @c M17NDIR + + m17n �ǡ����١����Υǡ������Ǽ�����ǥ��쥯�ȥ��̾�����ܺ٤� @ref + m17nDatabase ���ȡ� + +
  • @c MDEBUG_XXX + + "MDEBUG_" �ǻϤޤ�̾������ĴĶ��ѿ��ϥǥХå�����ν��Ϥ����椹�롣 + �ܺ٤� @ref m17nDebug ���ȡ� + +
+ + @em API @em ��̿̾��§ + + m17n �饤�֥��ϡ��ؿ����ѿ����ޥ��������� export ���롣������ 'm' + �ޤ��� 'M' �Τ��Ȥ˥��֥�������̾ ("symbol"��"plist" �ʤ�) + �ޤ��ϥ⥸�塼��̾ (draw, input �ʤ�) ��³������ΤǤ��롣 + M-text ���֥������Ȥ�̾���� "mmtext" �ǤϤʤ��� "mtext" + �ǻϤޤ뤳�Ȥ����ա� + +
    + +
  • �ؿ� -- mobject () �ޤ��� mobject_xxx () + + 'm' �Τ��Ȥ˾�ʸ���ǥ��֥�������̾��³����ñ��֤� '_' + �Ƕ��ڤ��롣���Ȥ��С�msymbol (), + mtext_ref_char (), mdraw_text () �ʤɡ� + +
  • ����ܥ�Ǥʤ��ѿ� -- mobject, �ޤ��� mobject_xxx + + �ؿ���Ʊ��̿̾��§�˽��������Ȥ��� mface_large �ʤɡ� + +
  • ����ܥ��ѿ� -- Mname + + MSymbol ���ѿ��ϡ�'M' �θ��̾����³����ñ��֤� '_' + �Ƕ��ڤ��롣���Ȥ��� Mlanguage (̾���� "language"), Miso_2022 + (̾����"iso-2022") �ʤɡ� + +
  • �ޥ��� -- MOBJECT_XXX + + 'M' �θ����ʸ���ǥ��֥�������̾��³����ñ��֤� '_' �Ƕ��ڤ��롣 + +
  • ������ -- MObject �ޤ��� MObjectXxx + + 'M' �θ����ʸ���ǻϤޤ륪�֥�������̾��³����ñ���Ϣ³���ƽ񤫤졢 + '_' ���Ѥ����ʤ������Ȥ��� MConverter, MInputDriver �ʤɡ� + +
+ + */ +/*=*/ +/*** @{ */ +#ifdef FOR_DOXYGEN +/***en + The #M17NLIB_MAJOR_VERSION macro gives the major version number + of the m17n library. */ +/***ja + �ޥ��� #M17NLIB_MAJOR_VERSION �� m17n + �饤�֥��Υ᥸�㡼�С�������ֹ��Ϳ����. */ + +#define M17NLIB_MAJOR_VERSION + +/*=*/ + +/***en + The #M17NLIB_MINOR_VERSION macro gives the minor version number + of the m17n library. */ + +/***ja + �ޥ��� #M17NLIB_MINOR_VERSION �� m17n + �饤�֥��Υޥ��ʡ��С�������ֹ��Ϳ����. */ + +#define M17NLIB_MINOR_VERSION + +/*=*/ + +/***en + The #M17NLIB_PATCH_LEVEL macro gives the patch level number + of the m17n library. */ + +/***ja + �ޥ��� #M17NLIB_PATCH_LEVEL �� m17n + �饤�֥��Υѥå���٥��ֹ��Ϳ����. */ + +#define M17NLIB_PATCH_LEVEL + +/*=*/ + +/***en + The #M17NLIB_VERSION_NAME macro gives the version name of the + m17n library as a string. */ + +/***ja + �ޥ��� #M17NLIB_VERSION_NAME �� m17n + �饤�֥��ΥС������̾��ʸ����Ȥ���Ϳ����. */ + +#define M17NLIB_VERSION_NAME + +/*=*/ + +/***en + @brief Initialize the m17n library. + + The macro M17N_INIT () initializes the m17n library. This macro + must be called before any m17n functions are used. + + It is safe to call this macro multiple times, but in that case, + the macro M17N_FINI () must be called the same times to free the + memory. + + If the initialization was successful, the external variable + #merror_code is set to 0. Otherwise it is set to -1. + + @seealso + M17N_FINI (), m17n_status () */ + +/***ja + @brief m17n �饤�֥�����������. + + �ޥ��� M17N_INIT () �� m17n �饤�֥����������롣m17n + �δؿ������Ѥ������ˡ����Υޥ�����ޤ��ƤФʤ��ƤϤʤ�ʤ��� + + ���Υޥ�����ʣ����Ƥ�Ǥ�����Ǥ��뤬�����ξ������������뤿��˥ޥ��� + M17N_FINI () ��Ʊ������Ƥ�ɬ�פ����롣 + + �����ѿ� #merror_code �ϡ����������������� 0 �ˡ������Ǥʤ���� + -1 �����ꤵ��롣 + + @seealso + M17N_FINI (), m17n_status () */ + +#define M17N_INIT() + +/*=*/ + +/***en + @brief Finalize the m17n library. + + The macro M17N_FINI () finalizes the m17n library. It frees all the + memory area used by the m17n library. Once this macro is + called, no m17n functions should be used until the + macro M17N_INIT () is called again. + + If the macro M17N_INIT () was called N times, the Nth call of this + macro actually free the memory. + + @seealso + M17N_INIT (), m17n_status () */ +/***ja + @brief m17n �饤�֥���λ����. + + �ޥ��� M17N_FINI () �� m17n �饤�֥���λ���롣m17n + �饤�֥�꤬�Ȥä����ƤΥ����ΰ�ϲ�������롣���٤��Υޥ������ƤФ줿�顢�ޥ��� + M17N_INIT () �����ٸƤФ��ޤ� m17n �ؿ��ϻȤ��٤��Ǥʤ��� + + �ޥ��� M17N_INIT () �� N ��ƤФ�Ƥ������ˤϡ����Υޥ����� N + ��ƤФ�ƽ��ƥ��꤬��������롣 + + @seealso + M17N_INIT (), m17n_status () */ + +#define M17N_FINI() +#endif /* FOR_DOXYGEN */ +/*=*/ +/*** @} */ +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include +#include +#include +#include +#include + +#include "m17n-core.h" +#include "m17n-misc.h" +#include "internal.h" +#include "symbol.h" + +static void +default_error_handler (enum MErrorCode err) +{ + exit (err); +} + +static struct timeval time_stack[16]; +static int time_stack_index; + +static M17NObjectArray *object_array_root; + +static void +report_object_array () +{ + fprintf (mdebug__output, "%16s %7s %7s %7s\n", + "object", "created", "freed", "alive"); + fprintf (mdebug__output, "%16s %7s %7s %7s\n", + "------", "-------", "-----", "-----"); + for (; object_array_root; object_array_root = object_array_root->next) + { + M17NObjectArray *array = object_array_root; + + fprintf (mdebug__output, "%16s %7d %7d %7d\n", array->name, + array->used, array->used - array->count, array->count); + if (array->count > 0) + { + int i; + for (i = 0; i < array->used && ! array->objects[i]; i++); + + if (strcmp (array->name, "M-text") == 0) + { + MText *mt = (MText *) array->objects[i]; + + if (mt->format <= MTEXT_FORMAT_UTF_8) + fprintf (mdebug__output, "\t\"%s\"\n", (char *) mt->data); + } + else if (strcmp (array->name, "Plist") == 0) + { + MPlist *plist = (MPlist *) array->objects[i]; + + mdebug_dump_plist (plist, 8); + fprintf (mdebug__output, "\n"); + } + } + + if (array->objects != NULL) + { + free (array->objects); + array->count = array->used = 0; + } + } +} + + + +/* Internal API */ + +int m17n__core_initialized; +int m17n__shell_initialized; +int m17n__gui_initialized; + +int mdebug__flags[MDEBUG_MAX]; +FILE *mdebug__output; + +void +mdebug__push_time () +{ + struct timezone tz; + + gettimeofday (time_stack + time_stack_index++, &tz); +} + +void +mdebug__pop_time () +{ + time_stack_index--; +} + +void +mdebug__print_time () +{ + struct timeval tv; + struct timezone tz; + long diff; + + gettimeofday (&tv, &tz); + diff = ((tv.tv_sec - time_stack[time_stack_index - 1].tv_sec) * 1000000 + + (tv.tv_usec - time_stack[time_stack_index - 1].tv_usec)); + fprintf (mdebug__output, "%8ld ms.", diff); + time_stack[time_stack_index - 1] = tv; +} + +static void +SET_DEBUG_FLAG (char *env_name, enum MDebugFlag flag) +{ + char *env_value = getenv (env_name); + + if (env_value) + { + int int_value = atoi (env_value); + + if (flag == MDEBUG_ALL) + { + int i; + for (i = 0; i < MDEBUG_MAX; i++) + mdebug__flags[i] = int_value; + } + else + mdebug__flags[flag] = int_value; + } +} + +void +mdebug__add_object_array (M17NObjectArray *array, char *name) +{ + array->name = name; + array->count = 0; + array->next = object_array_root; + object_array_root = array; +} + + +void +mdebug__register_object (M17NObjectArray *array, void *object) +{ + if (array->objects == NULL) + MLIST_INIT1 (array, objects, 256); + array->count++; + MLIST_APPEND1 (array, objects, object, MERROR_OBJECT); +} + +void +mdebug__unregister_object (M17NObjectArray *array, void *object) +{ + array->count--; + if (array->count >= 0) + { + int i; + + for (i = array->used - 1; i >= 0 && array->objects[i] != object; i--); + if (i >= 0) + { + if (i == array->used - 1) + array->used--; + array->objects[i] = NULL; + } + else + mdebug_hook (); + } + else \ + mdebug_hook (); +} + + +/* External API */ + +/* The following two are actually not exposed to a user but concealed + by the macro M17N_INIT (). */ + +void +m17n_init_core (void) +{ + int mdebug_flag = MDEBUG_INIT; + + merror_code = MERROR_NONE; + if (m17n__core_initialized++) + return; + + m17n_memory_full_handler = default_error_handler; + + SET_DEBUG_FLAG ("MDEBUG_ALL", MDEBUG_ALL); + SET_DEBUG_FLAG ("MDEBUG_INIT", MDEBUG_INIT); + SET_DEBUG_FLAG ("MDEBUG_FINI", MDEBUG_FINI); + SET_DEBUG_FLAG ("MDEBUG_CHARSET", MDEBUG_CHARSET); + SET_DEBUG_FLAG ("MDEBUG_CODING", MDEBUG_CODING); + SET_DEBUG_FLAG ("MDEBUG_DATABASE", MDEBUG_DATABASE); + SET_DEBUG_FLAG ("MDEBUG_FONT", MDEBUG_FONT); + SET_DEBUG_FLAG ("MDEBUG_FLT", MDEBUG_FLT); + SET_DEBUG_FLAG ("MDEBUG_FONTSET", MDEBUG_FONTSET); + SET_DEBUG_FLAG ("MDEBUG_INPUT", MDEBUG_INPUT); + /* for backward compatibility... */ + SET_DEBUG_FLAG ("MDEBUG_FONT_FLT", MDEBUG_FLT); + SET_DEBUG_FLAG ("MDEBUG_FONT_OTF", MDEBUG_FLT); + { + char *env_value = getenv ("MDEBUG_OUTPUT_FILE"); + + mdebug__output = NULL; + if (env_value) + { + if (strcmp (env_value, "stdout") == 0) + mdebug__output = stdout; + else + mdebug__output = fopen (env_value, "a"); + } + if (! mdebug__output) + mdebug__output = stderr; + } + + MDEBUG_PUSH_TIME (); + MDEBUG_PUSH_TIME (); + if (msymbol__init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize symbol module.")); + if (mplist__init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize plist module.")); + if (mchar__init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", + (mdebug__output, " to initialize character module.")); + if (mchartable__init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", + (mdebug__output, " to initialize chartable module.")); + if (mtext__init () < 0 || mtext__prop_init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize mtext module.")); + if (mdatabase__init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", + (mdebug__output, " to initialize database module.")); + +#if ENABLE_NLS + bindtextdomain ("m17n-lib", GETTEXTDIR); + bindtextdomain ("m17n-db", GETTEXTDIR); + bindtextdomain ("m17n-contrib", GETTEXTDIR); + bind_textdomain_codeset ("m17n-lib", "UTF-8"); + bind_textdomain_codeset ("m17n-db", "UTF-8"); + bind_textdomain_codeset ("m17n-contrib", "UTF-8"); +#endif + + err: + MDEBUG_POP_TIME (); + MDEBUG_PRINT_TIME ("INIT", + (mdebug__output, " to initialize the core modules.")); + MDEBUG_POP_TIME (); +} + +void +m17n_fini_core (void) +{ + int mdebug_flag = MDEBUG_FINI; + + if (m17n__core_initialized == 0 + || --m17n__core_initialized > 0) + return; + + MDEBUG_PUSH_TIME (); + MDEBUG_PUSH_TIME (); + mchartable__fini (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize chartable module.")); + mtext__fini (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize mtext module.")); + msymbol__fini (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize symbol module.")); + mplist__fini (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize plist module.")); + /* We must call this after the aboves because it frees interval + pools. */ + mtext__prop_fini (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize textprop module.")); + MDEBUG_POP_TIME (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize the core modules.")); + MDEBUG_POP_TIME (); + if (mdebug__flags[MDEBUG_FINI]) + report_object_array (); + msymbol__free_table (); + if (mdebug__output != stderr) + fclose (mdebug__output); +} + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ +/*=*/ + +/*** @addtogroup m17nIntro */ + +/*** @{ */ +/*=*/ + +/***en + @brief Report which part of the m17n library is initialized. + + The m17n_status () function returns one of these values depending + on which part of the m17n library is initialized: + + #M17N_NOT_INITIALIZED, #M17N_CORE_INITIALIZED, + #M17N_SHELL_INITIALIZED, #M17N_GUI_INITIALIZED */ + +/***ja + @brief m17n �饤�֥��Τɤ���ʬ����������줿����𤹤�. + + �ؿ� m17n_status () �� + m17n �饤�֥��Τɤ���ʬ����������줿���˱����ơ��ʲ����ͤΤ����줫���֤��� + + #M17N_NOT_INITIALIZED, #M17N_CORE_INITIALIZED, + #M17N_SHELL_INITIALIZED, #M17N_GUI_INITIALIZED */ + +enum M17NStatus +m17n_status (void) +{ + return (m17n__gui_initialized ? M17N_GUI_INITIALIZED + : m17n__shell_initialized ? M17N_SHELL_INITIALIZED + : m17n__core_initialized ? M17N_CORE_INITIALIZED + : M17N_NOT_INITIALIZED); +} + +/*** @} */ + +/*=*/ +/***en + @addtogroup m17nObject + @brief Managed objects are objects managed by the reference count. + + There are some types of m17n objects that are managed by their + reference count. Those objects are called @e managed @e objects. + When created, the reference count of a managed object is + initialized to one. The m17n_object_ref () function increments + the reference count of a managed object by one, and the + m17n_object_unref () function decrements by one. A managed + object is automatically freed when its reference count becomes + zero. + + A property whose key is a managing key can have only a managed + object as its value. Some functions, for instance msymbol_put () + and mplist_put (), pay special attention to such a property. + + In addition to the predefined managed object types, users can + define their own managed object types. See the documentation of + the m17n_object () for more details. */ +/***ja + @addtogroup m17nObject + @brief ���������֥������ȤȤϻ��ȿ��ˤ�äƴ�������Ƥ��륪�֥������ȤǤ���. + + m17n ���֥������ȤΤ��뷿�Τ�Τϡ����ȿ��ˤ�äƴ�������Ƥ��롣 + �����Υ��֥������Ȥ� @e ���������֥������� �ȸƤФ�롣�������줿�����Ǥλ��ȿ��� + 1 �˽��������Ƥ��롣�ؿ� m17n_object_ref () �ϴ��������֥������Ȥλ��ȿ��� + 1 ���䤷���ؿ�m17n_object_unref () �� 1 ���餹�����ȿ��� + 0 �ˤʤä����������֥������Ȥϼ�ưŪ�˲�������롣 + + ���������������Ǥ���ץ��ѥƥ��ϡ��ͤȤ��ƴ��������֥������Ȥ������롣 + �ؿ� msymbol_put () �� mplist_put () �ʤɤϤ����Υץ��ѥƥ������̰������롣 + + ����Ѥߴ��������֥������ȥ����פ�¾�ˡ��桼����ɬ�פʴ��������֥������ȥ����פ�ʬ��������뤳�Ȥ��Ǥ��롣�ܺ٤� + m17n_object () �������򻲾ȡ� */ + +/*** @{ */ +/*=*/ +/***en + @brief Allocate a managed object. + + The m17n_object () function allocates a new managed object of + $SIZE bytes and sets its reference count to 1. $FREER is the + function that is used to free the object when the reference count + becomes 0. If $FREER is NULL, the object is freed by the free () + function. + + The heading bytes of the allocated object is occupied by + #M17NObjectHead. That area is reserved for the m17n library and + application programs should never touch it. + + @return + This function returns a newly allocated object. + + @errors + This function never fails. */ + +/***ja + @brief ���������֥������Ȥ������Ƥ�. + + �ؿ� m17n_object () ��$SIZE �Х��Ȥο��������������֥������Ȥ������ơ����λ��ȿ��� + 1 �Ȥ��롣 $FREER �ϻ��ȿ��� 0 + �ˤʤä��ݤˤ��Υ��֥������Ȥ�������뤿����Ѥ�����ؿ��Ǥ��롣$FREER + �� NULL�ʤ�С����֥������Ȥϴؿ� free () �ˤ�äƲ�������롣 + + ������Ƥ�줿���֥���������Ƭ�ΥХ��Ȥϡ�#M17NObjectHead + �����롣�����ΰ�� m17n �饤�֥�꤬���Ѥ���Τǡ����ץꥱ�������ץ������Ͽ���ƤϤʤ�ʤ��� + + @return + ���δؿ��Ͽ�����������Ƥ�줿���֥������Ȥ��֤��� + + @errors + ���δؿ��ϼ��Ԥ��ʤ��� */ + +#if EXAMPLE_CODE +typedef struct +{ + M17NObjectHead head; + int mem1; + char *mem2; +} MYStruct; + +void +my_freer (void *obj) +{ + free (((MYStruct *) obj)->mem2); + free (obj); +} + +void +my_func (MText *mt, MSymbol key, int num, char *str) +{ + MYStruct *st = m17n_object (sizeof (MYStruct), my_freer); + + st->mem1 = num; + st->mem2 = strdup (str); + /* KEY must be a managing key. */ + mtext_put_prop (mt, 0, mtext_len (mt), key, st); + /* This sets the reference count of ST back to 1. */ + m17n_object_unref (st); +} +#endif + +void * +m17n_object (int size, void (*freer) (void *)) +{ + M17NObject *obj = malloc (size); + + obj->ref_count = 1; + obj->ref_count_extended = 0; + obj->flag = 0; + obj->u.freer = freer; + return obj; +} + +/*=*/ + +/***en + @brief Increment the reference count of a managed object. + + The m17n_object_ref () function increments the reference count of + the managed object pointed to by $OBJECT. + + @return + This function returns the resulting reference count if it fits in + a 16-bit unsigned integer (i.e. less than 0x10000). Otherwise, it + return -1. + + @errors + This function never fails. */ +/***ja + @brief ���������֥������Ȥλ��ȿ��� 1 ���䤹. + + �ؿ� m17n_object_ref () �� $OBJECT + �ǻؤ������������֥������Ȥλ��ȿ��� 1 ���䤹�� + + @return + ���δؿ��ϡ����䤷�����ȿ��� 16 �ӥåȤ����̵��������(���ʤ�� + 0x10000 ̤��)�ˤ����ޤ�С�������֤��������Ǥʤ���� -1 ���֤��� + + @errors + ���δؿ��ϼ��Ԥ��ʤ��� */ + +int +m17n_object_ref (void *object) +{ + M17NObject *obj = (M17NObject *) object; + M17NObjectRecord *record; + unsigned *count; + + if (! obj->ref_count_extended) + { + if (++obj->ref_count) + return (int) obj->ref_count; + MSTRUCT_MALLOC (record, MERROR_OBJECT); + record->freer = obj->u.freer; + MLIST_INIT1 (record, counts, 1); + MLIST_APPEND1 (record, counts, 0, MERROR_OBJECT); + obj->u.record = record; + obj->ref_count_extended = 1; + } + else + record = obj->u.record; + + count = record->counts; + while (*count == 0xFFFFFFFF) + *(count++) = 0; + (*count)++; + if (*count == 0xFFFFFFFF) + MLIST_APPEND1 (record, counts, 0, MERROR_OBJECT); + return -1; +} + +/*=*/ + +/***en + @brief Decrement the reference count of a managed object. + + The m17n_object_unref () function decrements the reference count + of the managed object pointed to by $OBJECT. When the reference + count becomes zero, the object is freed by its freer function. + + @return + This function returns the resulting reference count if it fits in + a 16-bit unsigned integer (i.e. less than 0x10000). Otherwise, it + returns -1. Thus, the return value zero means that $OBJECT is + freed. + + @errors + This function never fails. */ +/***ja + @brief ���������֥������Ȥλ��ȿ��� 1 ���餹. + + �ؿ� m17n_object_unref () �� $OBJECT �ǻؤ������������֥������Ȥλ��ȿ��� + 1 ���餹�����ȿ��� 0 �ˤʤ�С����֥������Ȥϲ����ؿ��ˤ�äƲ�������롣 + + @return + ���δؿ��ϡ����餷�����ȿ��� 16 �ӥåȤ����̵��������(���ʤ�� + 0x10000 ̤��)�ˤ����ޤ�С�������֤��������Ǥʤ���� -1 + ���֤����Ĥޤꡢ0 ���֤ä��褿����$OBJECT �ϲ�������Ƥ��롣 + + @errors + ���δؿ��ϼ��Ԥ��ʤ��� */ +int +m17n_object_unref (void *object) +{ + M17NObject *obj = (M17NObject *) object; + M17NObjectRecord *record; + unsigned *count; + + if (! obj->ref_count_extended) + { + if (! --obj->ref_count) + { + if (obj->u.freer) + (obj->u.freer) (object); + else + free (object); + return 0; + } + return (int) obj->ref_count; + } + + record = obj->u.record; + count = record->counts; + while (! *count) + *(count++) = 0xFFFFFFFF; + (*count)--; + if (! record->counts[0]) + { + obj->ref_count_extended = 0; + obj->ref_count--; + obj->u.freer = record->freer; + MLIST_FREE1 (record, counts); + free (record); + } + return -1; +} + +/*=*/ + +/*** @} */ + +/***en + @addtogroup m17nError Error Handling + @brief Error handling of the m17n library. + + There are two types of errors that may happen in a function of + the m17n library. + + The first type is argument errors. When a library function is + called with invalid arguments, it returns a value that indicates + error and at the same time sets the external variable #merror_code + to a non-zero integer. + + The second type is memory allocation errors. When the required + amount of memory is not available on the system, m17n library + functions call a function pointed to by the external variable @c + m17n_memory_full_handler. The default value of the variable is a + pointer to the default_error_handle () function, which just calls + exit (). */ + +/***ja + @addtogroup m17nError ���顼���� + @brief m17n �饤�֥��Υ��顼����. + + m17n �饤�֥��δؿ��Ǥϡ����Ĥμ���Υ��顼�����������롣 + + ��Ĥϰ����Υ��顼�Ǥ��롣 + �饤�֥��δؿ��������Ǥʤ������ȤȤ�˸ƤФ줿��硢���δؿ��ϥ��顼���̣�����ͤ��֤���Ʊ���˳����ѿ� + #merror_code �˥����Ǥʤ������򥻥åȤ��롣 + + �⤦��Ĥμ���ϥ�������ƥ��顼�Ǥ��롣 + �����ƥबɬ�פ��̤Υ��������Ƥ뤳�Ȥ��Ǥ��ʤ���硢�饤�֥��ؿ��ϳ����ѿ� + @c m17n_memory_full_handler ���ؤ��ؿ���Ƥ֡��ǥե���ȤǤϡ��ؿ� + default_error_handle () ��ؤ��Ƥ��ꡢ���δؿ���ñ�� exit + () ��Ƥ֡� +*/ + +/*** @{ */ + +/*=*/ + +/***en + @brief External variable to hold error code of the m17n library. + + The external variable #merror_code holds an error code of the + m17n library. When a library function is called with an invalid + argument, it sets this variable to one of @c enum #MErrorCode. + + This variable initially has the value 0. */ + +/***ja + @brief m17n �饤�֥��Υ��顼�����ɤ��ݻ����볰���ѿ�. + + �����ѿ� #merror_code �ϡ�m17n �饤�֥��Υ��顼�����ɤ��ݻ����롣 + �饤�֥��ؿ��������Ǥʤ������ȤȤ�˸ƤФ줿�ݤˤϡ������ѿ��� + @c enum #MErrorCode �ΰ�Ĥ˥��åȤ��롣 + + �����ѿ��ν���ͤ� 0 �Ǥ��롣 */ + +int merror_code; + +/*=*/ + +/***en + @brief Memory allocation error handler. + + The external variable #m17n_memory_full_handler holds a pointer + to the function to call when a library function failed to allocate + memory. $ERR is one of @c enum #MErrorCode indicating in which + function the error occurred. + + This variable initially points a function that simply calls the + exit () function with $ERR as an argument. + + An application program that needs a different error handling can + change this variable to point a proper function. */ + +/***ja + @brief ��������ƥ��顼�ϥ�ɥ�. + + �ѿ� #m17n_memory_full_handler + �ϡ��饤�֥��ؿ�����������Ƥ˼��Ԥ����ݤ˸Ƥ֤٤��ؿ��ؤΥݥ��󥿤Ǥ��롣 + $ERR �� @c enum #MErrorCode + �Τ����Τ����줫�Ǥ��ꡢ�ɤΥ饤�֥��ؿ��ǥ��顼�����ä����򼨤��� + + @anchor test + + �������Ǥϡ������ѿ���ñ�� exit () �� $ERR + ������Ȥ��ƸƤִؿ���ؤ��Ƥ��롣 + + ����Ȥϰۤʤ륨�顼������ɬ�פȤ��륢�ץꥱ�������ϡ������ѿ���Ŭ���ʴؿ������ꤹ�뤳�Ȥǡ���Ū��ã���Ǥ��롣 */ + +void (*m17n_memory_full_handler) (enum MErrorCode err); + +/*** @} */ + +/*=*/ + +/***en + @addtogroup m17nDebug + @brief Support for m17n library users to debug their programs. + + The m17n library provides the following facilities to support the + library users to debug their programs. + +
    + +
  • Environment variables to control printing of various + information to stderr. + +
      + +
    • MDEBUG_INIT -- If set to 1, print information about the + library initialization on the call of M17N_INIT (). + +
    • MDEBUG_FINI -- If set to 1, print counts of objects that are + not yet freed on the call of M17N_FINI (). + +
    • MDEBUG_CHARSET -- If set to 1, print information about + charsets being loaded from the m17n database. + +
    • MDEBUG_CODING -- If set to 1, print information about coding + systems being loaded from the m17n database. + +
    • MDEBUG_DATABASE -- If set to 1, print information about + data being loaded from the m17n database. + +
    • MDEBUG_FONT -- If set to 1, print information about fonts + being selected and opened. + +
    • MDEBUG_FLT -- If set to 1, 2, or 3, print information about + which command of Font Layout Table are being executed. The bigger + number prints the more detailed information. + +
    • MDEBUG_INPUT -- If set to 1, print information about how an + input method is running. + +
    • MDEBUG_ALL -- Setting this variable to 1 is equivalent to + setting all the above variables to 1. + +
    • MDEBUG_OUTPUT_FILE -- If set to a file name, the above + debugging information is appended to the file. If set to + "stdout", the information is printed to stdout. + +
    + +
  • Functions to print various objects in a human readable way. + See the documentation of mdebug_dump_XXXX () functions. + +
  • The hook function called on an error. See the documentation + of mdebug_hook (). + +
+*/ +/***ja + @addtogroup m17nDebug + @brief m17n �饤�֥��桼���Τ���Υץ������ǥХå����ݡ���. + + m17n �饤�֥��ϡ����Υ桼������ʬ�Υץ�������ǥХå����뤿��ˡ��ʲ��ε�ǽ�򥵥ݡ��Ȥ��Ƥ��롣 + +
    + +
  • ���ޤ��ޤʾ����ɸ�२�顼���ϤؤΥץ��Ȥ����椹��Ķ��ѿ��� + +
      + +
    • MDEBUG_INIT -- 1 �ʤ�С�M17N_INIT () + ���ƤФ줿�����ǡ��饤�֥��ν�����˴ؤ�������ץ��Ȥ��롣 + +
    • MDEBUG_FINI -- 1 �ʤ�С�M17N_FINI () + ���ƤФ줿�����ǡ��ޤ���������Ƥ��ʤ����֥������Ȥλ��ȿ���ץ��Ȥ��롣 + +
    • MDEBUG_CHARSET -- 1 �ʤ�С�m17n + �ǡ����١�����������ɤ��줿ʸ�����åȤˤĤ��Ƥξ����ץ��Ȥ��롣 + +
    • MDEBUG_CODING -- 1 �ʤ�С�m17n + �ǡ����١�����������ɤ��줿�����ɷϤˤĤ��Ƥξ����ץ��Ȥ��롣 + +
    • MDEBUG_DATABASE -- 1 �ʤ�С�m17n + �ǡ����١�����������ɤ��줿�ǡ����ˤĤ��Ƥξ����ץ��Ȥ��롣 + +
    • MDEBUG_FONT -- 1 �ʤ�С����򤵤�ƥ����ץ󤵤줿�ե���Ȥˤ� + ���Ƥξ����ץ��Ȥ��롣 + +
    • MDEBUG_FLT -- 1��2���⤷���� 3 �ʤ�С�Font Layout Table �Τ� + �Υ��ޥ�ɤ��¹��椫�ˤĤ��ƤΤ�ץ��Ȥ��롣����礭���������� + ���������ץ��Ȥ��롣 + +
    • MDEBUG_INPUT -- 1 �ʤ�С��¹�������ϥ᥽�åɤξ��֤��դ��Ƥ� + �����ץ��Ȥ��롣 + +
    • MDEBUG_ALL -- 1 �ʤ�С��嵭���٤Ƥ��ѿ��� 1 + �ˤ����Τ�Ʊ�����̤���ġ� + +
    • MDEBUG_OUTPUT_FILE -- �⤷�ե�����̾�ʤ顢�嵭�ǥХå�����Ϥ� + �Υե�������ɲä���롣�⤷ "stdout" �ʤ餽�ξ����ɸ����Ϥ˽��� + ����롣 + +
    + +
  • ��Υ��֥������Ȥ�ʹ֤˲��ɤʷ��ǥץ��Ȥ���ؿ����ܺ٤ϴؿ� + mdebug_dump_XXXX () ���������ȡ� + +
  • ���顼ȯ�����˸ƤФ��եå��ؿ���mdebug_hook () ���������ȡ� + +
+*/ + +/*=*/ +/*** @{ */ +/*=*/ + +/***en + @brief Hook function called on an error. + + The mdebug_hook () function is called when an error happens. It + returns -1 without doing anything. It is useful to set a break + point on this function in a debugger. */ +/***ja + @brief ���顼�κݤ˸ƤФ��եå��ؿ�. + + �ؿ� mdebug_hook () �ϥ��顼�������ä��ݤ˸ƤФ졢���⤻����-1 + ���֤����ǥХå���ǥ֥졼���ݥ���Ȥ����ꤹ�뤿����Ѥ��뤳�Ȥ��Ǥ��롣 + */ + +int +mdebug_hook () +{ + return -1; +} + +/*=*/ + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/m17n-core.h b/src/m17n-core.h new file mode 100644 index 0000000..42f0dd9 --- /dev/null +++ b/src/m17n-core.h @@ -0,0 +1,855 @@ +/* m17n-core.h -- header file for the CORE API of the m17n library. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_CORE_H_ +#define _M17N_CORE_H_ + +#ifdef __cplusplus +#define M17N_BEGIN_HEADER extern "C" { +#define M17N_END_HEADER } +#else +#define M17N_BEGIN_HEADER /* do nothing */ +#define M17N_END_HEADER /* do nothing */ +#endif + +M17N_BEGIN_HEADER + +/* + * Header file for m17n library. + */ + +/* (C1) Introduction */ + +/***en @defgroup m17nIntro Introduction */ +/***ja @defgroup m17nIntro �Ϥ���� */ +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) + +#define M17NLIB_MAJOR_VERSION 1 +#define M17NLIB_MINOR_VERSION 8 +#define M17NLIB_PATCH_LEVEL 0 +#define M17NLIB_VERSION_NAME "1.8.0" + +extern void m17n_init_core (void); +#define M17N_INIT() m17n_init_core () +extern void m17n_fini_core (void); +#define M17N_FINI() m17n_fini_core () + +extern int merror_code; + +#endif + +/*=*/ + +/*** @ingroup m17nIntro */ +/***en + @brief Enumeration for the status of the m17n library. + + The enum #M17NStatus is used as a return value of the function + m17n_status (). */ + +/***ja + @brief m17n �饤�֥��ξ��֤򼨤����. + + ��� #M17NStatus �ϴؿ� m17n_status () ������ͤȤ����Ѥ����롣 */ + +enum M17NStatus + { + /***en No modules is initialized, and all modules are finalized. */ + M17N_NOT_INITIALIZED, + /***en Only the modules in CORE API are initialized. */ + M17N_CORE_INITIALIZED, + /***en Only the modules in CORE and SHELL APIs are initialized. */ + M17N_SHELL_INITIALIZED, + /***en All modules are initialized. */ + M17N_GUI_INITIALIZED + }; + +/*=*/ + +extern enum M17NStatus m17n_status (void); + +/***en @defgroup m17nCore CORE API + @brief API provided by libm17n-core.so */ +/***ja @defgroup m17nCore ���� API + @brief libm17n-core.so ���󶡤��� API */ +/*=*/ +/*** @ingroup m17nCore */ +/***en @defgroup m17nObject Managed Object + @brief Objects managed by the reference count */ +/***ja @defgroup m17nObject ���������֥������� + @brief ���Ȳ���Ǵ�������륪�֥������� */ +/*=*/ + +/*** @ingroup m17nObject */ +/***en + @brief The first member of a managed object. + + When an application program defines a new structure for managed + objects, its first member must be of the type @c struct + #M17NObjectHead. Its contents are used by the m17n library, and + application programs should never touch them. */ +/***ja + @brief ���������֥������Ȥκǽ�Υ���. + + ���ץꥱ�������ץ�����ब��������¤�Τ���������֥������ȤȤ����������ݤˤϡ��ǽ�Υ��Ф� + @c #M17NObjectHead ��¤�η��Ǥʤ��ƤϤʤ�ʤ��� + @c #M17NObjectHead �����Ƥ� m17n + �饤�֥�꤬���Ѥ���Τǡ����ץꥱ�������ץ������Ͽ���ƤϤʤ�ʤ��� */ + +typedef struct +{ + /*** Hidden from applications. */ + void *filler[2]; +} M17NObjectHead; + +/*=*/ + +/* Return a newly allocated managed object. */ +extern void *m17n_object (int size, void (*freer) (void *)); + +/* Increment the reference count of managed object OBJECT. */ +extern int m17n_object_ref (void *object); + +/* Decrement the reference count of managed object OBJECT. */ +extern int m17n_object_unref (void *object); + +/*** @ingroup m17nCore */ +/***en + @brief Generic function type. + + #M17NFunc is a generic function type for setting a function + pointer as a value of #MSymbol property or #MPlist. */ + +/***ja + @brief �ƴؿ���. + + #M17NFunc ���ƴؿ����Ǥ��ꡢ�ؿ��ݥ��󥿤� #MSymbol �ץ��ѥƥ��� + #MPlist ���ͤȤ������ꤹ����Ѥ��롣 */ + + +/*** + @seealso + msymbol_put_func (), msymbol_get_func (), + mplist_put_func (), mplist_get_func (). */ + +typedef void (*M17NFunc) (void); + +/*=*/ + +/*** @ingroup m17nCore */ +/***en + @brief Wrapper for a generic function type. + + The macro M17N_FUNC () casts a function to the type #M17NFunc. */ + +/***ja + @brief �ƴؿ����ؤΥ�å�. + + �ޥ��� M17N_FUNC () �ϴؿ��� #M17NFunc ���إ��㥹�Ȥ��롣 */ + + +#define M17N_FUNC(func) ((M17NFunc) (func)) + +/*=*/ + +/* (C2) Symbol handling */ + +/*** @ingroup m17nCore */ +/***en @defgroup m17nSymbol Symbol */ +/***ja @defgroup m17nSymbol ����ܥ� */ +/*=*/ + +/*** + @ingroup m17nSymbol */ +/***en + @brief Type of symbols. + + The type #MSymbol is for a @e symbol object. Its internal + structure is concealed from application programs. */ + +/***ja + @brief ����ܥ�η����. + + #MSymbol �� @e ����ܥ� (symbol) ���֥������Ȥη��Ǥ��롣 + ������¤�ϥ��ץꥱ�������ץ�����फ��ϸ����ʤ��� */ + +typedef struct MSymbolStruct *MSymbol; + +/*=*/ + +/* Predefined symbols. */ +extern MSymbol Mnil; +extern MSymbol Mt; +extern MSymbol Mstring; +extern MSymbol Msymbol; +extern MSymbol Mtext; +extern MSymbol Mcharset; + +/* Return a symbol of name NAME. */ +extern MSymbol msymbol (const char *name); + +/* Return a managing key of name NAME. */ +extern MSymbol msymbol_as_managing_key (const char *name); + +/* Check if SYMBOL is a managing key. */ +extern int msymbol_is_managing_key (MSymbol symbol); + +/* Return a symbol of name NAME if it already exists. */ +extern MSymbol msymbol_exist (const char *name); + +/* Return the name of SYMBOL. */ +extern char *msymbol_name (MSymbol symbol); + +/* Give SYMBOL KEY property with value VALUE. */ +extern int msymbol_put (MSymbol symbol, MSymbol key, void *val); + +/*** Return KEY property value of SYMBOL. */ +extern void *msymbol_get (MSymbol symbol, MSymbol key); + +extern int msymbol_put_func (MSymbol symbol, MSymbol key, M17NFunc func); + +extern M17NFunc msymbol_get_func (MSymbol symbol, MSymbol key); + +/* + * (2-1) Property List + */ +/*=*/ +/*** @ingroup m17nCore */ +/***en @defgroup m17nPlist Property List */ +/***ja @defgroup m17nPlist �ץ��ѥƥ��ꥹ�� */ +/*=*/ + +/*** + @ingroup m17nPlist */ +/***en + @brief Type of property list objects. + + The type #MPlist is for a @e property @e list object. Its internal + structure is concealed from application programs. */ + +/***ja + @brief �ץ��ѥƥ��ꥹ�ȡ����֥������Ȥη����. + + #MPlist �� @e �ץ��ѥƥ��ꥹ�� (Property list) ���֥������Ȥη��Ǥ��롣 + ������¤�ϥ��ץꥱ�������ץ�����फ��ϸ����ʤ��� */ + +typedef struct MPlist MPlist; + +/*=*/ + +extern MSymbol Mplist, Minteger; + +extern MPlist *mplist (); + +extern MPlist *mplist_copy (MPlist *plist); + +extern MPlist *mplist_add (MPlist *plist, MSymbol key, void *val); + +extern MPlist *mplist_push (MPlist *plist, MSymbol key, void *val); + +extern void *mplist_pop (MPlist *plist); + +extern MPlist *mplist_put (MPlist *plist, MSymbol key, void *val); + +extern void *mplist_get (MPlist *plist, MSymbol key); + +extern MPlist *mplist_put_func (MPlist *plist, MSymbol key, M17NFunc func); + +extern M17NFunc mplist_get_func (MPlist *plist, MSymbol key); + +extern MPlist *mplist_find_by_key (MPlist *plist, MSymbol key); + +extern MPlist *mplist_find_by_value (MPlist *plist, void *val); + +extern MPlist *mplist_next (MPlist *plist); + +extern MPlist *mplist_set (MPlist *plist, MSymbol key, void *val); + +extern int mplist_length (MPlist *plist); + +extern MSymbol mplist_key (MPlist *plist); + +extern void *mplist_value (MPlist *plist); + +/* (S1) Characters */ + +/*=*/ +/*** @ingroup m17nCore */ +/***en @defgroup m17nCharacter Character */ +/***ja @defgroup m17nCharacter ʸ�� */ +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +#define MCHAR_MAX 0x3FFFFF +/*#define MCHAR_MAX 0x7FFFFFFF*/ +#endif + +extern MSymbol Mscript; +extern MSymbol Mname; +extern MSymbol Mcategory; +extern MSymbol Mcombining_class; +extern MSymbol Mbidi_category; +extern MSymbol Msimple_case_folding; +extern MSymbol Mcomplicated_case_folding; +extern MSymbol Mcased, Msoft_dotted, Mcase_mapping; +extern MSymbol Mblock; + +extern MSymbol mchar_define_property (const char *name, MSymbol type); + +extern void *mchar_get_prop (int c, MSymbol key); + +extern int mchar_put_prop (int c, MSymbol key, void *val); + +/* (C3) Handling chartable */ + +/*** @ingroup m17nCore */ +/***en @defgroup m17nChartable Chartable */ +/***ja @defgroup m17nChartable ʸ���ơ��֥� */ +/*=*/ +extern MSymbol Mchar_table; + +/*** + @ingroup m17nChartable */ +/***en + @brief Type of chartables. + + The type #MCharTable is for a @e chartable objects. Its + internal structure is concealed from application programs. */ + +/***ja + @brief ʸ���ơ��֥�η����. + + #MCharTable �� @e ʸ���ơ��֥� (chartable) ���֥������Ȥη��Ǥ��롣 + ������¤�ϥ��ץꥱ�������ץ�����फ��ϸ����ʤ��� */ + +typedef struct MCharTable MCharTable; +/*=*/ + +extern MCharTable *mchartable (MSymbol key, void *default_value); + +extern int mchartable_min_char (MCharTable *table); + +extern int mchartable_max_char (MCharTable *table); + +extern void *mchartable_lookup (MCharTable *table, int c); + +extern int mchartable_set (MCharTable *table, int c, void *val); + +extern int mchartable_set_range (MCharTable *table, int from, int to, + void *val); + +extern int mchartable_map (MCharTable *table, void *ignore, + void (*func) (int, int, void *, void *), + void *func_arg); + +extern void mchartable_range (MCharTable *table, int *from, int *to); + +extern MCharTable *mchar_get_prop_table (MSymbol key, MSymbol *type); + +/* + * (5) Handling M-text. + * "M" of M-text stands for: + * o Multilingual + * o Metamorphic + * o More than string + */ + +/*** @ingroup m17nCore */ +/***en @defgroup m17nMtext M-text */ +/***ja @defgroup m17nMtext M-text */ +/*=*/ + +/* + * (5-1) M-text basics + */ +/*=*/ +/*** @ingroup m17nMtext */ +/***en + @brief Type of @e M-texts. + + The type #MText is for an @e M-text object. Its internal + structure is concealed from application programs. */ + +/***ja + @brief @e MText �η����. + + #Mtext �� @e M-text ���֥������Ȥη��Ǥ��롣 + ������¤�ϥ��ץꥱ�������ץ�����फ��ϸ����ʤ��� + + @latexonly \IPAlabel{MText} @endlatexonly + @latexonly \IPAlabel{MText->MPlist} @endlatexonly */ + +typedef struct MText MText; + +/*=*/ + +/*** @ingroup m17nMtext */ +/***en + @brief Enumeration for specifying the format of an M-text. + + The enum #MTextFormat is used as an argument of the + mtext_from_data () function to specify the format of data from + which an M-text is created. */ + +/***ja + @brief M-text �Υե����ޥåȤ���ꤹ�����. + + ��� #MTextFormat �ϴؿ� + mtext_from_data () �ΰ����Ȥ����Ѥ���졢 + M-text ���������븵�Ȥʤ�ǡ����Υե����ޥåȤ���ꤹ�롣 */ + +enum MTextFormat + { + /*** US-ASCII encoding */ + MTEXT_FORMAT_US_ASCII, + /*** UTF-8 encoding */ + MTEXT_FORMAT_UTF_8, + /*** UTF-16LE encoding */ + MTEXT_FORMAT_UTF_16LE, + /*** UTF-16BE encoding */ + MTEXT_FORMAT_UTF_16BE, + /*** UTF-32LE encoding */ + MTEXT_FORMAT_UTF_32LE, + /*** UTF-32BE encoding */ + MTEXT_FORMAT_UTF_32BE, + MTEXT_FORMAT_MAX + }; +/*=*/ + +extern MText *mtext (); + +extern void *mtext_data (MText *mt, enum MTextFormat *fmt, int *nunits, + int *pos_idx, int *unit_idx); + +/*=*/ + +/***en @name Variables: Default Endian of UTF-16 and UTF-32 */ +/***ja @name �ѿ�: UTF-16 �� UTF-32 �Υǥե���ȤΥ���ǥ����� */ +/*** @{ */ +/*=*/ + +/*** @ingroup m17nMtext */ +/***en + @brief Variable of value MTEXT_FORMAT_UTF_16LE or MTEXT_FORMAT_UTF_16BE. + + The global variable #MTEXT_FORMAT_UTF_16 is initialized to + #MTEXT_FORMAT_UTF_16LE on a "Little Endian" system (storing words + with the least significant byte first), and to + #MTEXT_FORMAT_UTF_16BE on a "Big Endian" system (storing words + with the most significant byte first). */ + +/***ja + @brief �ͤ� MTEXT_FORMAT_UTF_16LE �� MTEXT_FORMAT_UTF_16BE �Ǥ����ѿ� + + ����ѿ� #MTEXT_FORMAT_UTF_16 �ϥ�ȥ롦����ǥ����󡦥����ƥ� + �ʥ�ɤ� LSB (Least Significant Byte) ����ˤ��Ƴ�Ǽ�˾�Ǥ� + #MTEXT_FORMAT_UTF_16LE �˽�������졢�ӥå�������ǥ����󡦥����ƥ� + �ʥ�ɤ� MSB (Most Significant Byte) ����ˤ��Ƴ�Ǽ�˾�Ǥ� + #MTEXT_FORMAT_UTF_16BE �˽��������롣 */ + +/*** + @seealso + mtext_from_data () */ + +extern const enum MTextFormat MTEXT_FORMAT_UTF_16; +/*=*/ + +/*** @ingroup m17nMtext */ +/***en + @brief Variable of value MTEXT_FORMAT_UTF_32LE or MTEXT_FORMAT_UTF_32BE. + + The global variable #MTEXT_FORMAT_UTF_32 is initialized to + #MTEXT_FORMAT_UTF_32LE on a "Little Endian" system (storing words + with the least significant byte first), and to + #MTEXT_FORMAT_UTF_32BE on a "Big Endian" system (storing + words with the most significant byte first). */ + +/***ja + @brief �ͤ� MTEXT_FORMAT_UTF_32LE �� MTEXT_FORMAT_UTF_32BE �Ǥ����ѿ� + + ����ѿ� #MTEXT_FORMAT_UTF_32 �ϥ�ȥ롦����ǥ����󡦥����ƥ� + �ʥ�ɤ� LSB (Least Significant Byte) ����ˤ��Ƴ�Ǽ�˾�Ǥ� + #MTEXT_FORMAT_UTF_32LE �˽�������졢�ӥå�������ǥ����󡦥����ƥ� + �ʥ�ɤ� MSB (Most Significant Byte) ����ˤ��Ƴ�Ǽ�˾�Ǥ� + #MTEXT_FORMAT_UTF_32BE �˽��������롣 */ + +/*** + @seealso + mtext_from_data () */ + +extern const int MTEXT_FORMAT_UTF_32; + +/*=*/ +/*** @} */ +/*=*/ + +extern MText *mtext_from_data (const void *data, int nitems, + enum MTextFormat format); + +/*=*/ +/*** @} */ + +extern MSymbol Mlanguage; + +/* + * (5-2) Functions to manipulate M-texts. They correspond to string + * manipulating functions in libc. + * In the following functions, mtext_XXX() corresponds to strXXX(). + */ + +extern int mtext_len (MText *mt); + +extern int mtext_ref_char (MText *mt, int pos); + +extern int mtext_set_char (MText *mt, int pos, int c); + +extern MText *mtext_copy (MText *mt1, int pos, MText *mt2, int from, int to); + +extern int mtext_compare (MText *mt1, int from1, int to1, + MText *mt2, int from2, int to2); + +extern int mtext_case_compare (MText *mt1, int from1, int to1, + MText *mt2, int from2, int to2); + +extern int mtext_character (MText *mt, int from, int to, int c); + +extern int mtext_del (MText *mt, int from, int to); + +extern int mtext_ins (MText *mt1, int pos, MText *mt2); + +extern int mtext_insert (MText *mt1, int pos, MText *mt2, int from, int to); + +extern int mtext_ins_char (MText *mt, int pos, int c, int n); + +extern int mtext_replace (MText *mt1, int from1, int to1, + MText *mt2, int from2, int to2); + +extern MText *mtext_cat_char (MText *mt, int c); + +extern MText *mtext_duplicate (MText *mt, int from, int to); + +extern MText *mtext_dup (MText *mt); + +extern MText *mtext_cat (MText *mt1, MText *mt2); + +extern MText *mtext_ncat (MText *mt1, MText *mt2, int n); + +extern MText *mtext_cpy (MText *mt1, MText *mt2); + +extern MText *mtext_ncpy (MText *mt1, MText *mt2, int n); + +extern int mtext_chr (MText *mt, int c); + +extern int mtext_rchr (MText *mt, int c); + +extern int mtext_cmp (MText *mt1, MText *mt2); + +extern int mtext_ncmp (MText *mt1, MText *mt2, int n); + +extern int mtext_spn (MText *mt1, MText *mt2); + +extern int mtext_cspn (MText *mt1, MText *mt2); + +extern int mtext_pbrk (MText *mt1, MText *mt2); + +extern int mtext_text (MText *mt1, int pos, MText *mt2); + +extern int mtext_search (MText *mt1, int from, int to, MText *mt2); + +extern MText *mtext_tok (MText *mt, MText *delim, int *pos); + +extern int mtext_casecmp (MText *mt1, MText *mt2); + +extern int mtext_ncasecmp (MText *mt1, MText *mt2, int n); + +extern int mtext_lowercase (MText *mt); + +extern int mtext_titlecase (MText *mt); + +extern int mtext_uppercase (MText *mt); + +/*** @ingroup m17nMtext */ +/***en + @brief Enumeration for specifying a set of line breaking option. + + The enum #MTextLineBreakOption is to control the line breaking + algorithm of the function mtext_line_break () by specifying + logical-or of the members in the arg @e option. */ + +enum MTextLineBreakOption + { + /***en Specify the legacy support for space character as base for + combining marks. See the section 8.3 of UAX#14. */ + MTEXT_LBO_SP_CM = 1, + /***en Specify to use space characters for line breaking Korean + text. */ + MTEXT_LBO_KOREAN_SP = 2, + /***en Specify to treat characters of ambiguous line-breaking + class as of ideographic line-breaking class. */ + MTEXT_LBO_AI_AS_ID = 4, + MTEXT_LBO_MAX + }; + +extern int mtext_line_break (MText *mt, int pos, int option, int *after); + +/*** @ingroup m17nPlist */ +extern MPlist *mplist_deserialize (MText *mt); + +/* + * (5-3) Text properties + */ +/*=*/ +/*** @ingroup m17nCore */ +/***en @defgroup m17nTextProperty Text Property */ +/***ja @defgroup m17nTextProperty �ƥ����ȥץ��ѥƥ� */ +/*=*/ +/*** @ingroup m17nTextProperty */ +/***en + @brief Flag bits to control text property. + + The mtext_property () function accepts logical OR of these flag + bits as an argument. They control the behaviour of the created + text property as described in the documentation of each flag + bit. */ + +/***ja + @brief �ƥ����ȥץ��ѥƥ������椹��ե饰�ӥå�. + + �ؿ� mtext_property () �ϰʲ��Υե饰�ӥåȤ����� + OR ������Ȥ��ƤȤ뤳�Ȥ��Ǥ��롣 + �ե饰�ӥåȤ��������줿�ƥ����ȥץ��ѥƥ��ο��񤤤����椹�롣 + �ܺ٤ϳƥե饰�ӥåȤ������򻲾ȡ�*/ + +enum MTextPropertyControl + { + /***en If this flag bit is on, an M-text inserted at the start + position or at the middle of the text property inherits the + text property. */ + /***ja ���ΥӥåȤ� on �ʤ�С����Υƥ����ȥץ��ѥƥ��λϤޤ������뤤����֤��������줿 + M-text �Ϥ��Υƥ����ȥץ��ѥƥ���Ѿ����롣 + */ + MTEXTPROP_FRONT_STICKY = 0x01, + + /***en If this flag bit is on, an M-text inserted at the end + position or at the middle of the text property inherits the + text property. */ + /***ja ���ΥӥåȤ� on �ʤ�С����Υƥ����ȥץ��ѥƥ��ν���������뤤����֤��������줿 + M-text �Ϥ��Υƥ����ȥץ��ѥƥ���Ѿ����롣 + */ + MTEXTPROP_REAR_STICKY = 0x02, + + /***en If this flag bit is on, the text property is removed if a + text in its region is modified. */ + /***ja ���ΥӥåȤ� on �ʤ�С����Υƥ����ȥץ��ѥƥ����ϰ���Υƥ����Ȥ��ѹ����줿���ƥ����ȥץ��ѥƥ��ϼ�������롣 */ + MTEXTPROP_VOLATILE_WEAK = 0x04, + + /***en If this flag bit is on, the text property is removed if a + text or the other text property in its region is modified. */ + /***ja ���ΥӥåȤ� on �ʤ�С����Υƥ����ȥץ��ѥƥ����ϰ���Υƥ����Ȥ��뤤���̤Υƥ����ȥץ��ѥƥ����ѹ����줿��礳�Υƥ� + ���ȥץ��ѥƥ��ϼ�������롣*/ + MTEXTPROP_VOLATILE_STRONG = 0x08, + + /***en If this flag bit is on, the text property is not + automatically merged with the others. */ + /***ja ���ΥӥåȤ� on �ʤ�С����Υƥ����ȥץ��ѥƥ���¾�Υץ��ѥƥ��ȼ�ưŪ�ˤϥޡ�������ʤ��� */ + MTEXTPROP_NO_MERGE = 0x10, + + MTEXTPROP_CONTROL_MAX = 0x1F + }; + +/*=*/ +extern MSymbol Mtext_prop_serializer; +extern MSymbol Mtext_prop_deserializer; + + +/*** @ingroup m17nTextProperty */ +/***en + @brief Type of serializer functions. + + This is the type of serializer functions. If the key of a symbol + property is #Mtext_prop_serializer, the value must be of this + type. + + @seealso + mtext_serialize (), #Mtext_prop_serializer +*/ +/***ja + @brief ���ꥢ�饤���ؿ��η����. + + ���ꥢ�饤���ؿ��η��Ǥ��롣 ���륷��ܥ�Υץ��ѥƥ��Υ����� @c + #Mtext_prop_serializer �Ǥ���Ȥ��� �ͤϤ��η��Ǥʤ��ƤϤʤ�ʤ��� + + @seealso + mtext_serialize (), #Mtext_prop_serializer +*/ + +typedef MPlist *(*MTextPropSerializeFunc) (void *val); + +/*** @ingroup m17nTextProperty */ +/***en + @brief Type of deserializer functions. + + This is the type of deserializer functions. If the key of a + symbol property is #Mtext_prop_deserializer, the value must be of + this type. + + @seealso + mtext_deserialize (), #Mtext_prop_deserializer +*/ +/***ja + @brief �ǥ��ꥢ�饤���ؿ��η����. + + �ǥ��ꥢ�饤���ؿ��η��Ǥ��롣 ���륷��ܥ�Υץ��ѥƥ��Υ����� @c + #Mtext_prop_deserializer �Ǥ���Ȥ��� �ͤϤ��η��Ǥʤ��ƤϤʤ�ʤ��� + + @seealso + Mtext_prop_deserialize (), Mtext_prop_deserializer +*/ +typedef void *(*MTextPropDeserializeFunc) (MPlist *plist); + +extern void *mtext_get_prop (MText *mt, int pos, MSymbol key); + +extern int mtext_get_prop_values (MText *mt, int pos, MSymbol key, + void **values, int num); + +extern int mtext_get_prop_keys (MText *mt, int pos, MSymbol **keys); + +extern int mtext_put_prop (MText *mt, int from, int to, + MSymbol key, void *val); + +extern int mtext_put_prop_values (MText *mt, int from, int to, + MSymbol key, void **values, int num); + +extern int mtext_push_prop (MText *mt, int from, int to, + MSymbol key, void *val); + +extern int mtext_pop_prop (MText *mt, int from, int to, + MSymbol key); + +extern int mtext_prop_range (MText *mt, MSymbol key, int pos, + int *from, int *to, int deeper); + +/*=*/ +/*** + @ingroup m17nTextProperty */ +/***en + @brief Type of text properties. + + The type #MTextProperty is for a @e text @e property objects. Its + internal structure is concealed from application programs. */ +/***ja + @brief @c �ƥ����ȥץ��ѥƥ��η����. + + #MTextProperty �� @e �ƥ����ȥץ��ѥƥ� ���֥������Ȥη��Ǥ��롣 + ������¤�ϥ��ץꥱ�������ץ�����फ��ϸ����ʤ��� */ + +typedef struct MTextProperty MTextProperty; + +/*=*/ + +extern MTextProperty *mtext_property (MSymbol key, void *val, + int control_bits); + +extern MText *mtext_property_mtext (MTextProperty *prop); + +extern MSymbol mtext_property_key (MTextProperty *prop); + +extern void *mtext_property_value (MTextProperty *prop); + +extern int mtext_property_start (MTextProperty *prop); + +extern int mtext_property_end (MTextProperty *prop); + +extern MTextProperty *mtext_get_property (MText *mt, int pos, MSymbol key); + +extern int mtext_get_properties (MText *mt, int pos, MSymbol key, + MTextProperty **props, int num); + +extern int mtext_attach_property (MText *mt, int from, int to, + MTextProperty *prop); + +extern int mtext_detach_property (MTextProperty *prop); + +extern int mtext_push_property (MText *mt, int from, int to, + MTextProperty *prop); + +extern MText *mtext_serialize (MText *mt, int from, int to, + MPlist *property_list); + +extern MText *mtext_deserialize (MText *mt); + +/*** @ingroup m17nCore */ +/***en @defgroup m17nDatabase Database */ +/***ja @defgroup m17nDatabase �ǡ����١��� */ +/*=*/ + +/* Directory of an application specific databases. */ +extern char *mdatabase_dir; +/*=*/ +/*** + @ingroup m17nDatabase */ +/***en + @brief Type of database. + + The type #MDatabase is for a database object. Its internal + structure is concealed from an application program. */ +/***ja + @brief �ǡ����١����η����. + + #MDatabase ���ϥǡ����١������֥��������Ѥι�¤�ΤǤ��롣 + ������¤�ϥ��ץꥱ�������ץ�����फ��ϸ����ʤ��� + */ + +typedef struct MDatabase MDatabase; + +/*=*/ + +/* Look for a data. */ +extern MDatabase *mdatabase_find (MSymbol tag1, MSymbol tag2, + MSymbol tag3, MSymbol tag4); + +extern MPlist *mdatabase_list (MSymbol tag0, MSymbol tag1, + MSymbol tag2, MSymbol tag3); + +/* Load a data. */ +void *mdatabase_load (MDatabase *mdb); + +/* Get tags of a data. */ +extern MSymbol *mdatabase_tag (MDatabase *mdb); + +/* Define a data. */ +extern MDatabase *mdatabase_define (MSymbol tag1, MSymbol tag2, + MSymbol tag3, MSymbol tag4, + void *(*loader) (MSymbol *, void *), + void *extra_info); + +M17N_END_HEADER + +#endif /* _M17N_CORE_H_ */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/m17n-flt.c b/src/m17n-flt.c new file mode 100644 index 0000000..207cc1c --- /dev/null +++ b/src/m17n-flt.c @@ -0,0 +1,3268 @@ +/* m17n-flt.c -- Font Layout Table sub-module. + Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nFLT + @brief FLT support for a window system. + + This section defines the m17n FLT API concerning character + layouting facility using FLT (Font Layout Table). The format of + FLT is described in @ref mdbFLT. */ + +/***ja + @addtogroup m17nFLT + @brief ������ɥ������ƥ�Τ���� FLT ���ݡ���. + + ���Υ��������Ǥϡ�FLT (Font Layout Table) + ���Ѥ���ʸ���쥤�����ȵ�ǽ�˴ؤ��� m17n FLT API ��������롣 + FLT �η����� @ref mdbFLT �˵��Ҥ���Ƥ��롣 */ + +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "m17n-core.h" +#include "m17n-flt.h" +#include "m17n-misc.h" +#include "internal.h" +#include "mtext.h" +#include "symbol.h" +#include "plist.h" +#include "database.h" +#include "internal-flt.h" + +/* Font Layouter */ + +/* Font Layout Table (FLT) + +Predefined terms: SYMBOL, INTEGER, STRING + +FLT ::= '(' STAGE + ')' + +STAGE ::= CATEGORY-TABLE ? FONT-LAYOUT-RULE + +;; Each STAGE consumes a source (code sequence) and produces another +;; code sequence that is given to the next STAGE as a source. The +;; source given to the first stage is a sequence of character codes +;; that are assigned category codes by CATEGORY-TABLE. The output of +;; the last stage is a glyph code sequence given to the renderer. + +CATEGORY-TABLE ::= + '(' 'category' CATEGORY-SPEC + ')' +CATEGORY-SPEC ::= + '(' CODE [ CODE ] CATEGORY ')' +CODE ::= INTEGER +CATEGORY ::= INTEGER +;; ASCII character codes of alphabet ('A' .. 'Z' 'a' .. 'z'). +;; Ex: CATEGORY-TABLE +;; (category +;; (0x0900 0x097F ?E) ; All Devanagari characters +;; (0x093C ?N)) ; DEVANAGARI-LETTER NUKTA +;; Assign the category 'E' to all Devanagari characters but 0x093C, +;; assign the category 'N' to 0x093C. + +FONT-LAYOUT-RULE ::= + '(' 'generator' RULE MACRO-DEF * ')' + +RULE ::= COMMAND | REGEXP-RULE | MATCH-RULE | MAP-RULE + | COND-STRUCT | MACRO-NAME + +COMMAND ::= + DIRECT-CODE | COMBINING | PREDEFIND-COMMAND | OTF-COMMAND + +DIRECT-CODE ::= INTEGER +;; Always succeed. Produce the code. Consume no source. + +PREDEFIND-COMMAND ::= + '=' | '*' | '<' | '>' | '|' + +;; '=': Succeed when the current run contains at least one code. +;; Consume the first code in the current run, and produce it as is. + +;; '*': If the the previous command succeeded, repeat it until it +;; fails. + +;; '<': Produce a special code that indicates the start of grapheme +;; cluster. Succeed always, consume nothing. + +;; '>': Produce a special code that indicates the end of grapheme +;; cluster. Succeed always, consume nothing. + +;; '|': Produce a special code whose category is ' '. Succeed always, +;; consume nothing. + +OTF-COMMAND ::= + ':otf=''SCRIPT'[':'['LANGSYS'][':'[GSUB-FEATURES][':'GPOS-FEATURES]]] +;; Run the Open Type Layout Table on the current run. Succeed always, +;; consume all glyphs in the current range. + +SCRIPT ::= OTF-TAG +;; OTF's ScriptTag name (four letters) listed at: +;; +LANGSYS ::= OTF-TAG +;; OTF's Language System name (four letters) listed at: +;; + +GSUB-FEATURES ::= [FEATURE[,FEATURE]*] | ' ' +GPOS-FEATURES ::= [FEATURE[,FEATURE]*] | ' ' +FEATURE ::= OTF-TAG +;; OTF's Feature name (four letters) listed at: +;; + +OTF-TAG ::= PRINTABLE-CHAR PRINTABLE-CHAR PRINTABLE-CHAR PRINTABLE-CHAR + +;; Ex. OTF-COMMAND +;; 'otf:deva' +;; Run all features in the default langsys of 'deva' script. +;; 'otf:deva::nukt:haln' +;; Run all GSUB features, run 'nukt' and 'haln' GPOS features. +;; 'otf:deva:: :' +;; Run all GSUB features, run no GPOS features. + +REGEXP-RULE ::= + '(' REGEXP RULE * ')' + +;; Succeed if REGXP matches the head of source. Run RULEs while +;; limiting the source to the matching part. Consume that part. + +REGEXP ::= STRING +;; Must be composed only from ASCII characters. 'A' - 'Z', 'a' - 'z' +;; correspond to CATEGORY. + +;; Ex: REGEXP-RULE +;; ("VA?" +;; < | vowel * | >) + +MATCH-RULE ::= + '(' MATCH-IDX RULE * ')' + +;; Succeed if the previous REGEXP-RULE found a matching part for +;; MATCH-IDX. Run RULEs while limiting the source to the matching +;; part. If MATCH-IDX is zero, consume the whole part, else consume +;; nothing. + +MATCH-IDX ::= INTEGER +;; Must be 0..20. + +;; Ex. MATCH-RULE +;; (2 consonant *) + +MAP-RULE ::= + '(' ( SOURCE-SEQ | SOURCE-RANGE ) RULE * ')' + +;; Succeed if the source matches SOURCE-SEQ or SOURCE-RANGE. Run +;; RULEs while limiting the source to the matching part. Consume that +;; part. + +SOURCE-SEQ ::= + '(' CODE + ')' +SOURCE-RANGE ::= + '(' 'range' CODE CODE ')' +;; Ex. MAP-RULE +;; ((0x0915 0x094D) 0x43) +;; If the source code sequence is 0x0915 0x094D, produce 0x43. +;; ((range 0x0F40 0x0F6A) 0x2221) +;; If the first source code CODE is in the range 0x0F40..0x0F6A, +;; produce (0x2221 + (CODE - 0x0F40)). + +COND-STRUCT ::= + '(' 'cond' RULE + ')' + +;; Try each rule in sequence until one succeeds. Succeed if one +;; succeeds. Consume nothing. + +;; Ex. COND-STRUCT +;; (cond +;; ((0x0915 0x094D) 0x43) +;; ((range 0x0F40 0x0F6A) 0x2221) +;; = ) + +COMBINING ::= 'V''H''O''V''H' +V ::= ( 't' | 'c' | 'b' | 'B' ) +H ::= ( 'l' | 'c' | 'r' ) +O ::= ( '.' | XOFF | YOFF | XOFF YOFF ) +XOFF ::= '<'INTEGER | '>'INTEGER +YOFF ::= '+'INTEGER | '-'INTEGER +;; INTEGER must be integer 0..127 + +;; VH pair indicates 12 reference points of a glyph as below: +;; +;; 0----1----2 <---- ascent 0:tl (top-left) +;; | | 1:tc (top-center) +;; | | 2:tr (top-right) +;; | | 3:Bl (base-left) +;; 9 10 11 <---- center 4:Bc (base-center) +;; | | 5:Br (base-right) +;; --3----4----5-- <-- baseline 6:bl (bottom-left) +;; | | 7:bc (bottom-center) +;; 6----7----8 <---- descent 8:br (bottom-right) +;; 9:cl (center-left) +;; | | | 10:cc (center-center) +;; left center right 11:cr (center-right) +;; +;; Ex. COMBINING +;; 'tc.bc': +;; Align top-left point of the previous glyph and bottom-center +;; point of the current glyph. +;; 'Bl<20-10Br' +;; Align 20% left and 10% below of base-left point of the previous +;; glyph and base-right point of the current glyph. + +MACRO-DEF ::= + '(' MACRO-NAME RULE + ')' +MACRO-NAME ::= SYMBOL + +*/ + +static int mdebug_flag = MDEBUG_FLT; + +MSymbol Mfont, Mlayouter, Mcombining; + +static MSymbol Mgenerator, Mend; + +static MPlist *flt_list; +static int flt_min_coverage, flt_max_coverage; + +enum GlyphInfoMask +{ + CategoryCodeMask = 0x7F, + CombiningCodeMask = 0xFFFFFF, + CombinedMask = 1 << 28, + LeftPaddingMask = 1 << 29, + RightPaddingMask = 1 << 30 +}; + +#define SET_GLYPH_INFO(g, mask, ctx, info) \ + ((g)->internal = (((g)->internal & ~(mask)) | (info)), \ + (ctx)->check_mask |= (mask)) + +#define GET_CATEGORY_CODE(g) ((g)->internal & CategoryCodeMask) +#define SET_CATEGORY_CODE(g, code) \ + ((g)->internal = (((g)->internal & ~(CombiningCodeMask | CombinedMask)) \ + | (code))) +#define GET_COMBINED(g) ((g)->internal & CombinedMask) +#define GET_COMBINING_CODE(g) ((g)->internal & CombiningCodeMask) +#define SET_COMBINING_CODE(g, ctx, code) \ + SET_GLYPH_INFO (g, CombiningCodeMask | CombinedMask, ctx, \ + (code) | CombinedMask) +#define GET_LEFT_PADDING(g) ((g)->internal & LeftPaddingMask) +#define SET_LEFT_PADDING(g, ctx, flag) \ + SET_GLYPH_INFO (g, LeftPaddingMask, ctx, flag) +#define GET_RIGHT_PADDING(g) ((g)->internal & RightPaddingMask) +#define SET_RIGHT_PADDING(g, ctx, flag) \ + SET_GLYPH_INFO (g, RightPaddingMask, ctx, flag) +#define GET_ENCODED(g) ((g)->encoded) +#define SET_ENCODED(g, flag) ((g)->encoded = (flag)) +#define GET_MEASURED(g) ((g)->measured) +#define SET_MEASURED(g, flag) ((g)->measured = (flag)) + +#define GINIT(gstring, n) \ + do { \ + if (! (gstring)->glyph_size) \ + (gstring)->glyph_size = sizeof (MFLTGlyph); \ + (gstring)->glyphs = alloca ((gstring)->glyph_size * (n)); \ + (gstring)->allocated = (n); \ + (gstring)->used = 0; \ + } while (0) + +#define GALLOCA (gstring) \ + ((MFLTGlyph *) alloca ((gstring)->glyph_size)) + +#define GREF(gstring, idx) \ + ((MFLTGlyph *) ((char *) ((gstring)->glyphs) + (gstring)->glyph_size * (idx))) + +#define PREV(gstring, g) \ + ((MFLTGlyph *) ((char *) (g) - (gstring)->glyph_size)) + +#define NEXT(gstring, g) \ + ((MFLTGlyph *) ((char *) (g) + (gstring)->glyph_size)) + +#define GCPY(src, src_idx, n, tgt, tgt_idx) \ + do { \ + memcpy ((char *) ((tgt)->glyphs) + (tgt)->glyph_size * (tgt_idx), \ + (char *) ((src)->glyphs) + (src)->glyph_size * (src_idx), \ + (src)->glyph_size * (n)); \ + } while (0) + +#define GDUP(ctx, idx) \ + do { \ + MFLTGlyphString *src = (ctx)->in; \ + MFLTGlyphString *tgt = (ctx)->out; \ + if (tgt->allocated <= tgt->used) \ + return -2; \ + GCPY (src, (idx), 1, tgt, tgt->used); \ + tgt->used++; \ + } while (0) + +static int +GREPLACE (MFLTGlyphString *src, int src_from, int src_to, + MFLTGlyphString *tgt, int tgt_from, int tgt_to) +{ + int src_len = src_to - src_from; + int tgt_len = tgt_to - tgt_from; + int inc = src_len - tgt_len; + + if (tgt->allocated < tgt->used + inc) + return -2; + if (inc != 0 && tgt_to < tgt->used) + memmove ((char *) tgt->glyphs + tgt->glyph_size * (tgt_from + src_len), + (char *) tgt->glyphs + tgt->glyph_size * tgt_to, + tgt->glyph_size * (tgt->used - tgt_to)); + if (src_len) + memcpy ((char *) tgt->glyphs + tgt->glyph_size * tgt_from, + (char *) src->glyphs + src->glyph_size * src_from, + src->glyph_size * src_len); + tgt->used += inc; + return 0; +} + + +/* Command ID: + 0 ... : direct code + -1 : invalid + -0x0F .. -2 : builtin commands + -0x100000F .. -0x10 : combining code + ... -0x1000010: index to FontLayoutStage->cmds + */ + +#define INVALID_CMD_ID -1 +#define CMD_ID_OFFSET_BUILTIN -3 +#define CMD_ID_OFFSET_COMBINING -0x10 +#define CMD_ID_OFFSET_INDEX -0x1000010 + +/* Builtin commands. */ +#define CMD_ID_COPY -3 /* '=' */ +#define CMD_ID_REPEAT -4 /* '*' */ +#define CMD_ID_CLUSTER_BEGIN -5 /* '<' */ +#define CMD_ID_CLUSTER_END -6 /* '>' */ +#define CMD_ID_SEPARATOR -7 /* '|' */ +#define CMD_ID_LEFT_PADDING -8 /* '[' */ +#define CMD_ID_RIGHT_PADDING -9 /* ']' */ + +#define CMD_ID_TO_COMBINING_CODE(id) (CMD_ID_OFFSET_COMBINING - (id)) +#define COMBINING_CODE_TO_CMD_ID(code) (CMD_ID_OFFSET_COMBINING - (code)) + +#define CMD_ID_TO_INDEX(id) (CMD_ID_OFFSET_INDEX - (id)) +#define INDEX_TO_CMD_ID(idx) (CMD_ID_OFFSET_INDEX - (idx)) + +static MSymbol Mcond, Mrange, Mfont_facility, Mequal; + +#define GLYPH_CODE_P(code) \ + ((code) >= GLYPH_CODE_MIN && (code) <= GLYPH_CODE_MAX) + +#define GLYPH_CODE_INDEX(code) ((code) - GLYPH_CODE_MIN) + +#define UPDATE_CLUSTER_RANGE(ctx, g) \ + do { \ + if (ctx->cluster_begin_pos > (g)->from) \ + ctx->cluster_begin_pos = (g)->from; \ + if (ctx->cluster_end_pos < (g)->to) \ + ctx->cluster_end_pos = (g)->to; \ + } while (0) + +enum FontLayoutCmdRuleSrcType + { + SRC_REGEX, + SRC_INDEX, + SRC_SEQ, + SRC_RANGE, + SRC_HAS_GLYPH, + SRC_OTF_SPEC + }; + +typedef struct +{ + enum FontLayoutCmdRuleSrcType src_type; + union { + struct { + char *pattern; + regex_t preg; + } re; + int match_idx; + struct { + int n_codes; + int *codes; + } seq; + struct { + int from, to; + } range; + struct { + int len; + MPlist *codes; + MFLTOtfSpec otf_spec; + } facility; + } src; + + int n_cmds; + int *cmd_ids; +} FontLayoutCmdRule; + +typedef struct +{ + /* Beginning and end indices of series of SEQ commands. */ + int seq_beg, seq_end; + /* Range of the first character appears in the above series. */ + int seq_from, seq_to; + + int n_cmds; + int *cmd_ids; +} FontLayoutCmdCond; + +enum FontLayoutCmdType + { + FontLayoutCmdTypeRule, + FontLayoutCmdTypeCond, + FontLayoutCmdTypeOTF, + FontLayoutCmdTypeOTFCategory, + FontLayoutCmdTypeMAX + }; + +typedef struct +{ + enum FontLayoutCmdType type; + union { + FontLayoutCmdRule rule; + FontLayoutCmdCond cond; + MFLTOtfSpec otf; + } body; +} FontLayoutCmd; + +typedef struct +{ + int size; + unsigned int *tag; + char *code; +} FeatureCodeTable; + +typedef struct +{ + MCharTable *table; + FeatureCodeTable feature_table; + /* Non-null if the table must be re-configured by OTF specs included + in the definition. */ + MPlist *definition; +} FontLayoutCategory; + +typedef struct +{ + FontLayoutCategory *category; + int size, inc, used; + FontLayoutCmd *cmds; +} FontLayoutStage; + +struct _MFLT +{ + MSymbol name; + MSymbol family; + MSymbol registry; + MFLTOtfSpec otf; + MDatabase *mdb; + FontLayoutCategory *coverage; + MPlist *stages; + int need_config; + /* Font for which coverage or some of categories are configured. */ + MSymbol font_id; +}; + +/* Font layout table loader */ + +static int parse_otf_command (MSymbol symbol, MFLTOtfSpec *spec); + +static void +apply_otf_feature (MFLTFont *font, MFLTOtfSpec *spec, + int from, int to, MCharTable *table, int category) +{ + unsigned char *buf; + int i; + + if (! mflt_iterate_otf_feature) + return; + buf = alloca (to + 1 - from); + memset (buf, 0, to + 1 - from); + if (mflt_iterate_otf_feature (font, spec, from, to, buf) < 0) + return; + for (i = to - from; i >= 0; i--) + if (buf[i]) + mchartable_set (table, from + i, (void *) category); +} + +static unsigned int gen_otf_tag (char *p, int shift); + +/* Load a category table from PLIST. PLIST has this form: + PLIST ::= ( FROM-CODE TO-CODE ? CATEGORY-CHAR ) * +*/ + +static FontLayoutCategory * +load_category_table (MPlist *plist, MFLTFont *font) +{ + FontLayoutCategory *category; + MCharTable *table; + MPlist *feature_table_head = NULL; + int feature_table_size = 0; + MPlist *p; + int need_otf = 0; + + table = mchartable (Minteger, (void *) 0); + MPLIST_DO (p, plist) + { + MPlist *elt; + int from, to, category_code; + + if (! MPLIST_PLIST_P (p)) + MERROR_GOTO (MERROR_FLT, end); + elt = MPLIST_PLIST (p); + if (MPLIST_SYMBOL_P (elt)) + { + MPlist *next; + + if (! mflt_enable_new_feature) + { + M17N_OBJECT_UNREF (table); + return NULL; + } + next = MPLIST_NEXT (elt); + if (! MPLIST_INTEGER_P (next)) + MERROR_GOTO (MERROR_FLT, end); + if (! feature_table_head) + feature_table_head = p; + feature_table_size++; + continue; + } + if (! MPLIST_INTEGER_P (elt)) + MERROR_GOTO (MERROR_FLT, end); + from = MPLIST_INTEGER (elt); + elt = MPLIST_NEXT (elt); + if (! MPLIST_INTEGER_P (elt)) + MERROR_GOTO (MERROR_FLT, end); + to = MPLIST_INTEGER (elt); + elt = MPLIST_NEXT (elt); + if (MPLIST_TAIL_P (elt)) + { + category_code = to; + to = from; + } + else if (MPLIST_SYMBOL_P (elt)) + { + if (! mflt_enable_new_feature) + { + M17N_OBJECT_UNREF (table); + return NULL; + } + if (font) + { + MFLTOtfSpec spec; + if (parse_otf_command (MPLIST_SYMBOL (elt), &spec) < 0) + MERROR_GOTO (MERROR_FLT, end); + elt = MPLIST_NEXT (elt); + if (! MPLIST_INTEGER_P (elt)) + MERROR_GOTO (MERROR_FLT, end); + category_code = MPLIST_INTEGER (elt); + if (! isalnum (category_code)) + MERROR_GOTO (MERROR_FLT, end); + apply_otf_feature (font, &spec, from, to, table, category_code); + } + else + need_otf = 1; + continue; + } + else + { + if (! MPLIST_INTEGER_P (elt)) + MERROR_GOTO (MERROR_FLT, end); + category_code = MPLIST_INTEGER (elt); + } + if (! isalnum (category_code)) + MERROR_GOTO (MERROR_FLT, end); + + if (from == to) + mchartable_set (table, from, (void *) category_code); + else + mchartable_set_range (table, from, to, (void *) category_code); + } + + end: + category = calloc (1, sizeof (FontLayoutCategory)); + category->table = table; + if (need_otf) + { + category->definition = plist; + M17N_OBJECT_REF (plist); + } + else + category->definition = NULL; + if (feature_table_head) + { + int i = 0; + category->feature_table.size = feature_table_size; + category->feature_table.tag = malloc (sizeof (unsigned int) + * feature_table_size); + category->feature_table.code = malloc (feature_table_size); + + MPLIST_DO (p, feature_table_head) + { + MPlist *elt; + MSymbol feature; + if (! MPLIST_PLIST_P (p)) + continue; + elt = MPLIST_PLIST (p); + if (! MPLIST_SYMBOL_P (elt)) + continue; + feature = MPLIST_SYMBOL (elt); + elt = MPLIST_NEXT (elt); + if (! MPLIST_INTEGER_P (elt)) + continue; + category->feature_table.tag[i] + = gen_otf_tag (MSYMBOL_NAME (feature), 7); + category->feature_table.code[i] = MPLIST_INTEGER (elt); + i++; + } + } + return category; +} + +#define ref_category_table(CATEGORY) M17N_OBJECT_REF ((CATEGORY)->table) + +static void +unref_category_table (FontLayoutCategory *category) +{ + M17N_OBJECT_UNREF (category->table); + if (! category->table) + { + if (category->definition) + M17N_OBJECT_UNREF (category->definition); + if (category->feature_table.size > 0) + { + free (category->feature_table.tag); + free (category->feature_table.code); + } + free (category); + } +} + +static unsigned int +gen_otf_tag (char *p, int shift) +{ + unsigned int tag = 0; + int i; + + for (i = 0; i < 4 && *p; i++, p++) + tag = (tag << shift) | *p; + for (; i < 4; i++) + tag = (tag << shift) | 0x20; + return tag; +} + +static char * +otf_count_features (char *p, char *end, char stopper, int *count) +{ + int negative = 0; + + *count = 0; + if (*p != stopper && *p != '\0') + while (1) + { + (*count)++; + if (*p == '*') + { + p++; + if (*p == stopper || *p == '\0') + break; + return NULL; + } + if (*p == '~') + { + if (negative++ == 0) + (*count)++; + p += 5; + } + else + p += 4; + if (p > end) + return NULL; + if (*p == stopper || *p == '\0') + break; + if (*p != ',') + return NULL; + p++; + if (! *p) + return NULL; + } + return p; +} + +static void +otf_store_features (char *p, char *end, unsigned *buf) +{ + int negative = 0; + int i; + + for (i = 0; p < end;) + { + if (*p == '*') + buf[i++] = 0xFFFFFFFF, p += 2, negative = 1; + else if (*p == '~') + { + if (negative++ == 0) + buf[i++] = 0xFFFFFFFF; + buf[i++] = gen_otf_tag (p + 1, 8), p += 6; + } + else + buf[i++] = gen_otf_tag (p, 8), p += 5; + } + buf[i] = 0; +} + +/* SYMBOL's name features[0] for checking for applying + features[1] GSUB GPOS GSUB GPOS + ------------- ------------------ ------------- ------------ + SCRIPT [-1,0] [-1,0] any | any all all + SCRIPT= NULL [-1,0] none & 1 none all + SCRIPT+ [-1,0] NULL 1 & none all none + SCRIPT=+ NULL NULL none & none none none + SCRIPT=F1 [F1,0] [-1,0] F1 & 1 F1 all + SCRIPT+F1 [-1][0] [F1,0] 1 & F1 none F1 + SCRIPT=F1+ [F1,0] NULL F1 & none F1 none + SCRIPT=~F2 [-1,F2,0] [-1,0] ~F2 & 1 all~F2 all + SCRIPT=F1,~F2 [F1,-1,F2,0][-1,0] F1&~F2 & 1 F1 (*1) all + + (*1) Invalid specification + */ + +static int +parse_otf_command (MSymbol symbol, MFLTOtfSpec *spec) +{ + char *str = MSYMBOL_NAME (symbol); + char *end = str + MSYMBOL_NAMELEN (symbol); + unsigned int script, langsys; + char *features[3]; + int feature_count[2]; /* [0]:GSUB, [1]:GPOS */ + int i; + char *p; + + memset (spec, 0, sizeof (MFLTOtfSpec)); + + spec->sym = symbol; + str += 5; /* skip the heading ":otf=" or ":otf?" */ + if (str[-1] == '?') + { + if (! mflt_enable_new_feature) + /* The client can't use this command. */ + return -1; + if (! *str) + /* This is a spec to reset category codes. */ + return 0; + } + spec->script = gen_otf_tag (str, 8); + str += 4; + if (*str == '/') + { + spec->langsys = gen_otf_tag (str, 8); + str += 4; + } + else + spec->langsys = 0; + features[0] = str; + if (*str != '=') + /* Apply all GSUB features. */ + feature_count[0] = -1; + else + { + p = str + 1; + str = otf_count_features (p, end, '+', feature_count); + if (! str) + MERROR (MERROR_FLT, -1); + } + features[1] = str; + if (*str != '+') + /* Apply all GPOS features. */ + feature_count[1] = -1; + else + { + p = str + 1; + str = otf_count_features (p, end, '\0', feature_count + 1); + if (! str) + MERROR (MERROR_FLT, -1); + } + features[2] = str; + for (i = 0; i < 2; i++) + if (feature_count[i]) + { + spec->features[i] = malloc (sizeof (int) + * (feature_count[i] < 0 ? 2 + : feature_count[i] + 1)); + if (! spec->features[i]) + return -2; + if (feature_count[i] > 0) + otf_store_features (features[i] + 1, features[i + 1], + spec->features[i]); + else + spec->features[i][0] = 0xFFFFFFFF, spec->features[i][1] = 0; + } + + return 0; +} + + +/* Parse OTF command name NAME and store the result in CMD. + NAME has this form: + :SCRIPT[/[LANGSYS][=[GSUB-FEATURES][+GPOS-FEATURES]]] + where GSUB-FEATURES and GPOS-FEATURES have this form: + [FEATURE[,FEATURE]*] | ' ' */ + +static int +load_otf_command (FontLayoutCmd *cmd, MSymbol sym) +{ + char *name = MSYMBOL_NAME (sym); + int result; + + if (name[0] != ':') + { + /* This is old format of "otf:...". Change it to ":otf=...". */ + char *str = alloca (MSYMBOL_NAMELEN (sym) + 2); + + sprintf (str, ":otf="); + strcat (str, name + 4); + sym = msymbol (str); + } + + result = parse_otf_command (sym, &cmd->body.otf); + if (result == -2) + return result; + cmd->type = (name[4] == '?' ? FontLayoutCmdTypeOTFCategory + : FontLayoutCmdTypeOTF); + return 0; +} + + +/* Read a decimal number from STR preceded by one of "+-><". '+' and + '>' means a plus sign, '-' and '<' means a minus sign. If the + number is greater than 127, limit it to 127. */ + +static int +read_decimal_number (char **str) +{ + char *p = *str; + int sign = (*p == '-' || *p == '<') ? -1 : 1; + int n = 0; + + p++; + while (*p >= '0' && *p <= '9') + n = n * 10 + *p++ - '0'; + *str = p; + if (n == 0) + n = 5; + return (n < 127 ? n * sign : 127 * sign); +} + + +/* Read a horizontal and vertical combining positions from STR, and + store them in the place pointed by X and Y. The horizontal + position left, center, and right are represented by 0, 1, and 2 + respectively. The vertical position top, center, bottom, and base + are represented by 0, 1, 2, and 3 respectively. If successfully + read, return 0, else return -1. */ + +static int +read_combining_position (char *str, int *x, int *y) +{ + int c = *str++; + int i; + + /* Vertical position comes first. */ + for (i = 0; i < 4; i++) + if (c == "tcbB"[i]) + { + *y = i; + break; + } + if (i == 4) + return -1; + c = *str; + /* Then comse horizontal position. */ + for (i = 0; i < 3; i++) + if (c == "lcr"[i]) + { + *x = i; + return 0; + } + return -1; +} + + +/* Return a combining code corresponding to SYM. */ + +static int +get_combining_command (MSymbol sym) +{ + char *str = msymbol_name (sym); + int base_x, base_y, add_x, add_y, off_x, off_y; + int c; + + if (read_combining_position (str, &base_x, &base_y) < 0) + return 0; + str += 2; + c = *str; + if (c == '.') + { + off_x = off_y = 128; + str++; + } + else + { + if (c == '+' || c == '-') + { + off_y = read_decimal_number (&str) + 128; + c = *str; + } + else + off_y = 128; + if (c == '<' || c == '>') + off_x = read_decimal_number (&str) + 128; + else + off_x = 128; + } + if (read_combining_position (str, &add_x, &add_y) < 0) + return 0; + + c = MAKE_COMBINING_CODE (base_y, base_x, add_y, add_x, off_y, off_x); + return (COMBINING_CODE_TO_CMD_ID (c)); +} + + +/* Load a command from PLIST into STAGE, and return that + identification number. If ID is not INVALID_CMD_ID, that means we + are loading a top level command or a macro. In that case, use ID + as the identification number of the command. Otherwise, generate a + new id number for the command. MACROS is a list of raw macros. */ + +static int +load_command (FontLayoutStage *stage, MPlist *plist, + MPlist *macros, int id) +{ + int i; + int result; + + if (MPLIST_INTEGER_P (plist)) + { + int code = MPLIST_INTEGER (plist); + + if (code < 0) + MERROR (MERROR_DRAW, INVALID_CMD_ID); + return code; + } + else if (MPLIST_PLIST_P (plist)) + { + /* PLIST ::= ( cond ... ) | ( STRING ... ) | ( INTEGER ... ) + | ( ( INTEGER INTEGER ) ... ) + | ( ( range INTEGER INTEGER ) ... ) + | ( ( SYMBOL STRING ) ... ) + | ( ( font-facilty [ INTEGER ] ) ... ) + | ( ( font-facilty OTF-SPEC ) ... ) */ + MPlist *elt = MPLIST_PLIST (plist); + int len = MPLIST_LENGTH (elt) - 1; + FontLayoutCmd *cmd; + + if (id == INVALID_CMD_ID) + { + FontLayoutCmd dummy; + id = INDEX_TO_CMD_ID (stage->used); + MLIST_APPEND1 (stage, cmds, dummy, MERROR_DRAW); + } + cmd = stage->cmds + CMD_ID_TO_INDEX (id); + + if (MPLIST_SYMBOL_P (elt)) + { + FontLayoutCmdCond *cond; + + if (MPLIST_SYMBOL (elt) != Mcond) + MERROR (MERROR_DRAW, INVALID_CMD_ID); + elt = MPLIST_NEXT (elt); + cmd->type = FontLayoutCmdTypeCond; + cond = &cmd->body.cond; + cond->seq_beg = cond->seq_end = -1; + cond->seq_from = cond->seq_to = 0; + cond->n_cmds = len; + MTABLE_CALLOC (cond->cmd_ids, len, MERROR_DRAW); + for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt)) + { + int this_id = load_command (stage, elt, macros, INVALID_CMD_ID); + + if (this_id == INVALID_CMD_ID || this_id == -2) + MERROR (MERROR_DRAW, this_id); + /* The above load_command may relocate stage->cmds. */ + cmd = stage->cmds + CMD_ID_TO_INDEX (id); + cond = &cmd->body.cond; + cond->cmd_ids[i] = this_id; + if (this_id <= CMD_ID_OFFSET_INDEX) + { + FontLayoutCmd *this_cmd + = stage->cmds + CMD_ID_TO_INDEX (this_id); + + if (this_cmd->type == FontLayoutCmdTypeRule + && this_cmd->body.rule.src_type == SRC_SEQ) + { + int first_char = this_cmd->body.rule.src.seq.codes[0]; + + if (cond->seq_beg < 0) + { + /* The first SEQ command. */ + cond->seq_beg = i; + cond->seq_from = cond->seq_to = first_char; + } + else if (cond->seq_end < 0) + { + /* The following SEQ command. */ + if (cond->seq_from > first_char) + cond->seq_from = first_char; + else if (cond->seq_to < first_char) + cond->seq_to = first_char; + } + } + else + { + if (cond->seq_beg >= 0 && cond->seq_end < 0) + /* The previous one is the last SEQ command. */ + cond->seq_end = i; + } + } + else + { + if (cond->seq_beg >= 0 && cond->seq_end < 0) + /* The previous one is the last SEQ command. */ + cond->seq_end = i; + } + } + if (cond->seq_beg >= 0 && cond->seq_end < 0) + /* The previous one is the last SEQ command. */ + cond->seq_end = i; + } + else + { + cmd->type = FontLayoutCmdTypeRule; + if (MPLIST_MTEXT_P (elt)) + { + MText *mt = MPLIST_MTEXT (elt); + char *str = (char *) MTEXT_DATA (mt); + + if (str[0] != '^') + { + mtext_ins_char (mt, 0, '^', 1); + str = (char *) MTEXT_DATA (mt); + } + if (regcomp (&cmd->body.rule.src.re.preg, str, REG_EXTENDED)) + MERROR (MERROR_FONT, INVALID_CMD_ID); + cmd->body.rule.src_type = SRC_REGEX; + cmd->body.rule.src.re.pattern = strdup (str); + } + else if (MPLIST_INTEGER_P (elt)) + { + cmd->body.rule.src_type = SRC_INDEX; + cmd->body.rule.src.match_idx = MPLIST_INTEGER (elt); + } + else if (MPLIST_PLIST_P (elt)) + { + MPlist *pl = MPLIST_PLIST (elt), *p; + int size = MPLIST_LENGTH (pl); + + if (MPLIST_INTEGER_P (pl)) + { + int i; + + cmd->body.rule.src_type = SRC_SEQ; + cmd->body.rule.src.seq.n_codes = size; + MTABLE_CALLOC (cmd->body.rule.src.seq.codes, size, + MERROR_FONT); + for (i = 0; i < size; i++, pl = MPLIST_NEXT (pl)) + { + if (! MPLIST_INTEGER_P (pl)) + MERROR (MERROR_DRAW, INVALID_CMD_ID); + cmd->body.rule.src.seq.codes[i] + = (unsigned) MPLIST_INTEGER (pl); + } + } + else if (MPLIST_SYMBOL_P (pl)) + { + if (MPLIST_SYMBOL (pl) == Mrange) + { + if (size != 3) + MERROR (MERROR_FLT, INVALID_CMD_ID); + cmd->body.rule.src_type = SRC_RANGE; + pl = MPLIST_NEXT (pl); + if (! MPLIST_INTEGER_P (pl)) + MERROR (MERROR_DRAW, INVALID_CMD_ID); + cmd->body.rule.src.range.from + = (unsigned) MPLIST_INTEGER (pl); + pl = MPLIST_NEXT (pl); + if (! MPLIST_INTEGER_P (pl)) + MERROR (MERROR_DRAW, INVALID_CMD_ID); + cmd->body.rule.src.range.to + = (unsigned) MPLIST_INTEGER (pl); + } + else if (MPLIST_SYMBOL (pl) == Mfont_facility) + { + FontLayoutCmdRule *rule = &cmd->body.rule; + + pl = MPLIST_NEXT (pl); + if (MPLIST_SYMBOL_P (pl)) + { + MSymbol sym = MPLIST_SYMBOL (pl); + char *otf_spec = MSYMBOL_NAME (sym); + + if (otf_spec[0] == ':' && otf_spec[1] == 'o' + && otf_spec[2] == 't' && otf_spec[3] == 'f') + parse_otf_command (sym, &rule->src.facility.otf_spec); + else + MERROR (MERROR_FLT, INVALID_CMD_ID); + rule->src_type = SRC_OTF_SPEC; + pl = MPLIST_NEXT (pl); + } + else if (MPLIST_TAIL_P (pl)) + MERROR (MERROR_FLT, INVALID_CMD_ID); + else + rule->src_type = SRC_HAS_GLYPH; + rule->src.facility.len = 0; + MPLIST_DO (p, pl) + { + if (! MPLIST_INTEGER_P (p) + && (MPLIST_SYMBOL_P (p) + ? MPLIST_SYMBOL (p) != Mequal + : 1)) + MERROR (MERROR_FLT, INVALID_CMD_ID); + rule->src.facility.len++; + } + rule->src.facility.codes = pl; + M17N_OBJECT_REF (pl); + } + } + else + MERROR (MERROR_DRAW, INVALID_CMD_ID); + } + else + MERROR (MERROR_DRAW, INVALID_CMD_ID); + + elt = MPLIST_NEXT (elt); + cmd->body.rule.n_cmds = len; + MTABLE_CALLOC (cmd->body.rule.cmd_ids, len, MERROR_DRAW); + for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt)) + { + int this_id = load_command (stage, elt, macros, INVALID_CMD_ID); + + if (this_id == INVALID_CMD_ID || this_id == -2) + MERROR (MERROR_DRAW, this_id); + /* The above load_command may relocate stage->cmds. */ + cmd = stage->cmds + CMD_ID_TO_INDEX (id); + cmd->body.rule.cmd_ids[i] = this_id; + } + } + } + else if (MPLIST_SYMBOL_P (plist)) + { + MPlist *elt; + MSymbol sym = MPLIST_SYMBOL (plist); + char *name = msymbol_name (sym); + int len = strlen (name); + FontLayoutCmd cmd; + + if (len > 4 + && ((name[0] == 'o' && name[1] == 't' + && name[2] == 'f' && name[3] == ':') + || (name[0] == ':' && name[1] == 'o' && name[2] == 't' + && name[3] == 'f' && (name[4] == '=' || name[4] == '?')))) + { + result = load_otf_command (&cmd, sym); + if (result < 0) + return result; + if (id == INVALID_CMD_ID) + { + id = INDEX_TO_CMD_ID (stage->used); + MLIST_APPEND1 (stage, cmds, cmd, MERROR_DRAW); + } + else + stage->cmds[CMD_ID_TO_INDEX (id)] = cmd; + return id; + } + + if (len == 1) + { + if (*name == '=') + return CMD_ID_COPY; + else if (*name == '*') + return CMD_ID_REPEAT; + else if (*name == '<') + return CMD_ID_CLUSTER_BEGIN; + else if (*name == '>') + return CMD_ID_CLUSTER_END; + else if (*name == '|') + return CMD_ID_SEPARATOR; + else if (*name == '[') + return CMD_ID_LEFT_PADDING; + else if (*name == ']') + return CMD_ID_RIGHT_PADDING; + else + id = 0; + } + else + { + id = get_combining_command (sym); + if (id) + return id; + } + + i = 1; + MPLIST_DO (elt, macros) + { + if (sym == MPLIST_SYMBOL (MPLIST_PLIST (elt))) + { + id = INDEX_TO_CMD_ID (i); + if (stage->cmds[i].type == FontLayoutCmdTypeMAX) + id = load_command (stage, MPLIST_NEXT (MPLIST_PLIST (elt)), + macros, id); + return id; + } + i++; + } + MERROR (MERROR_DRAW, INVALID_CMD_ID); + } + else + MERROR (MERROR_DRAW, INVALID_CMD_ID); + + return id; +} + +static void +free_flt_command (FontLayoutCmd *cmd) +{ + if (cmd->type == FontLayoutCmdTypeRule) + { + FontLayoutCmdRule *rule = &cmd->body.rule; + + if (rule->src_type == SRC_REGEX) + { + free (rule->src.re.pattern); + regfree (&rule->src.re.preg); + } + else if (rule->src_type == SRC_SEQ) + free (rule->src.seq.codes); + free (rule->cmd_ids); + } + else if (cmd->type == FontLayoutCmdTypeCond) + free (cmd->body.cond.cmd_ids); + else if (cmd->type == FontLayoutCmdTypeOTF + || cmd->type == FontLayoutCmdTypeOTFCategory) + { + if (cmd->body.otf.features[0]) + free (cmd->body.otf.features[0]); + if (cmd->body.otf.features[1]) + free (cmd->body.otf.features[1]); + } +} + +/* Load a generator from PLIST into a newly allocated FontLayoutStage, + and return it. PLIST has this form: + PLIST ::= ( COMMAND ( CMD-NAME COMMAND ) * ) +*/ + +static FontLayoutStage * +load_generator (MPlist *plist) +{ + FontLayoutStage *stage; + MPlist *elt, *pl; + FontLayoutCmd dummy; + int result; + + MSTRUCT_CALLOC (stage, MERROR_DRAW); + MLIST_INIT1 (stage, cmds, 32); + dummy.type = FontLayoutCmdTypeMAX; + MLIST_APPEND1 (stage, cmds, dummy, MERROR_FONT); + MPLIST_DO (elt, MPLIST_NEXT (plist)) + { + if (! MPLIST_PLIST_P (elt)) + MERROR (MERROR_FONT, NULL); + pl = MPLIST_PLIST (elt); + if (! MPLIST_SYMBOL_P (pl)) + MERROR (MERROR_FONT, NULL); + MLIST_APPEND1 (stage, cmds, dummy, MERROR_FONT); + } + + /* Load the first command from PLIST into STAGE->cmds[0]. Macros + called in the first command are also loaded from MPLIST_NEXT + (PLIST) into STAGE->cmds[n]. */ + result = load_command (stage, plist, MPLIST_NEXT (plist), + INDEX_TO_CMD_ID (0)); + if (result == INVALID_CMD_ID || result == -2) + { + MLIST_FREE1 (stage, cmds); + free (stage); + return NULL; + } + + return stage; +} + + +/* Load stages of the font layout table FLT. */ + +static int +load_flt (MFLT *flt, MPlist *key_list) +{ + MPlist *top, *plist, *pl, *p; + FontLayoutCategory *category = NULL; + MSymbol sym; + + if (key_list) + top = (MPlist *) mdatabase__load_for_keys (flt->mdb, key_list); + else + top = (MPlist *) mdatabase_load (flt->mdb); + if (! top) + return -1; + if (! MPLIST_PLIST_P (top)) + { + M17N_OBJECT_UNREF (top); + MERROR (MERROR_FLT, -1); + } + + if (key_list) + { + plist = mdatabase__props (flt->mdb); + if (! plist) + MERROR (MERROR_FLT, -1); + MPLIST_DO (plist, plist) + if (MPLIST_PLIST_P (plist)) + { + pl = MPLIST_PLIST (plist); + if (! MPLIST_SYMBOL_P (pl) + || MPLIST_SYMBOL (pl) != Mfont) + continue; + pl = MPLIST_NEXT (pl); + if (! MPLIST_PLIST_P (pl)) + continue; + p = MPLIST_PLIST (pl); + if (! MPLIST_SYMBOL_P (p)) + continue; + p = MPLIST_NEXT (p); + if (! MPLIST_SYMBOL_P (p)) + continue; + flt->family = MPLIST_SYMBOL (p); + MPLIST_DO (p, MPLIST_NEXT (p)) + if (MPLIST_SYMBOL_P (p)) + { + sym = MPLIST_SYMBOL (p); + if (MSYMBOL_NAME (sym)[0] != ':') + flt->registry = sym, sym = Mnil; + else + break; + } + if (sym) + { + char *otf_spec = MSYMBOL_NAME (sym); + + if (otf_spec[0] == ':' && otf_spec[1] == 'o' + && otf_spec[2] == 't' && otf_spec[3] == 'f') + parse_otf_command (sym, &flt->otf); + } + break; + } + } + MPLIST_DO (plist, top) + { + if (MPLIST_SYMBOL_P (plist) + && MPLIST_SYMBOL (plist) == Mend) + { + mplist_set (plist, Mnil, NULL); + break; + } + if (! MPLIST_PLIST (plist)) + continue; + pl = MPLIST_PLIST (plist); + if (! MPLIST_SYMBOL_P (pl)) + continue; + sym = MPLIST_SYMBOL (pl); + pl = MPLIST_NEXT (pl); + if (! pl) + continue; + if (sym == Mcategory) + { + if (category) + unref_category_table (category); + else if (flt->coverage) + { + category = flt->coverage; + ref_category_table (category); + continue; + } + category = load_category_table (pl, NULL); + if (! category) + goto err; + if (! flt->coverage) + { + flt->coverage = category; + ref_category_table (category); + } + if (category->definition) + flt->need_config = 1; + } + else if (sym == Mgenerator) + { + FontLayoutStage *stage; + + if (! category) + break; + stage = load_generator (pl); + if (! stage) + break; + stage->category = category; + M17N_OBJECT_REF (category->table); + if (! flt->stages) + flt->stages = mplist (); + mplist_add (flt->stages, Mt, stage); + } + } + if (category) + unref_category_table (category); + err: + if (! MPLIST_TAIL_P (plist)) + { + M17N_OBJECT_UNREF (top); + M17N_OBJECT_UNREF (flt->stages); + MERROR (MERROR_FLT, -1); + } + M17N_OBJECT_UNREF (top); + return 0; +} + + +static void +free_flt_stage (MFLT *flt, FontLayoutStage *stage) +{ + int i; + + unref_category_table (stage->category); + if (! flt->font_id) + { + for (i = 0; i < stage->used; i++) + free_flt_command (stage->cmds + i); + MLIST_FREE1 (stage, cmds); + } + free (stage); +} + +static void +free_flt_list () +{ + if (flt_list) + { + MPlist *plist, *pl; + + MPLIST_DO (plist, flt_list) + { + MFLT *flt = MPLIST_VAL (plist); + + if (flt->coverage) + unref_category_table (flt->coverage); + if (flt->stages) + { + MPLIST_DO (pl, MPLIST_NEXT (flt->stages)) + free_flt_stage (flt, MPLIST_VAL (pl)); + M17N_OBJECT_UNREF (flt->stages); + } + free (flt); + MPLIST_VAL (plist) = NULL; + } + M17N_OBJECT_UNREF (flt_list); + } +} + +static int +list_flt () +{ + MPlist *plist, *key_list = NULL; + MPlist *pl; + int result = 0; + + if (! (plist = mdatabase_list (Mfont, Mlayouter, Mnil, Mnil))) + return -1; + if (! (flt_list = mplist ())) + goto err; + if (! (key_list = mplist ())) + goto err; + if (! mplist_add (key_list, Mcategory, Mt)) + goto err; + + MPLIST_DO (pl, plist) + { + MDatabase *mdb = MPLIST_VAL (pl); + MSymbol *tags = mdatabase_tag (mdb); + MFLT *flt; + + if (! MSTRUCT_CALLOC_SAFE (flt)) + goto err; + flt->name = tags[2]; + flt->mdb = mdb; + if (load_flt (flt, key_list) < 0) + free (flt); + else + { + if (MPLIST_TAIL_P (flt_list)) + { + flt_min_coverage = mchartable_min_char (flt->coverage->table); + flt_max_coverage = mchartable_max_char (flt->coverage->table); + } + else + { + int c; + + c = mchartable_min_char (flt->coverage->table); + if (flt_min_coverage > c) + flt_min_coverage = c; + c = mchartable_max_char (flt->coverage->table); + if (flt_max_coverage < c) + flt_max_coverage = c; + } + if (! mplist_push (flt_list, flt->name, flt)) + goto err; + } + } + goto end; + + err: + free_flt_list (); + result = -1; + end: + M17N_OBJECT_UNREF (plist); + M17N_OBJECT_UNREF (key_list); + return result; +} + +/* FLS (Font Layout Service) */ + +/* Structure to hold information about a context of FLS. */ + +typedef struct +{ + /* Pointer to the current stage. */ + FontLayoutStage *stage; + + /* Pointer to the category table of the next stage or NULL if none. */ + FontLayoutCategory *category; + + /* Pointer to the font. */ + MFLTFont *font; + + /* Input and output glyph string. */ + MFLTGlyphString *in, *out; + + /* Encode each character or code of a glyph by the current category + table into this array. An element is a category letter used for + a regular expression matching. */ + char *encoded; + int encoded_offset; + int *match_indices; + int code_offset; + int cluster_begin_idx; + int cluster_begin_pos; + int cluster_end_pos; + int combining_code; + int left_padding; + int check_mask; +} FontLayoutContext; + +static int run_command (int, int, int, int, FontLayoutContext *); +static int run_otf (int, MFLTOtfSpec *, int, int, FontLayoutContext *); +static int try_otf (int, MFLTOtfSpec *, int, int, FontLayoutContext *); + +#define NMATCH 20 + +static int +run_rule (int depth, + FontLayoutCmdRule *rule, int from, int to, FontLayoutContext *ctx) +{ + int *saved_match_indices = ctx->match_indices; + int match_indices[NMATCH * 2]; + int consumed; + int i; + int orig_from = from; + int need_cluster_update = 0; + + if (rule->src_type == SRC_REGEX) + { + regmatch_t pmatch[NMATCH]; + char saved_code; + int result; + + if (from > to) + return 0; + saved_code = ctx->encoded[to - ctx->encoded_offset]; + ctx->encoded[to - ctx->encoded_offset] = '\0'; + result = regexec (&(rule->src.re.preg), + ctx->encoded + (from - ctx->encoded_offset), + NMATCH, pmatch, 0); + if (result == 0 && pmatch[0].rm_so == 0) + { + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT5 ("\n [FLT] %*s(REGEX \"%s\" \"%s\" %d", depth, "", + rule->src.re.pattern, + ctx->encoded + (from - ctx->encoded_offset), + pmatch[0].rm_eo); + ctx->encoded[to - ctx->encoded_offset] = saved_code; + for (i = 0; i < NMATCH; i++) + { + if (pmatch[i].rm_so < 0) + match_indices[i * 2] = match_indices[i * 2 + 1] = -1; + else + { + match_indices[i * 2] = from + pmatch[i].rm_so; + match_indices[i * 2 + 1] = from + pmatch[i].rm_eo; + } + } + ctx->match_indices = match_indices; + to = match_indices[1]; + } + else + { + ctx->encoded[to - ctx->encoded_offset] = saved_code; + return 0; + } + need_cluster_update = 1; + } + else if (rule->src_type == SRC_SEQ) + { + int len; + + len = rule->src.seq.n_codes; + if (len > (to - from)) + return 0; + for (i = 0; i < len; i++) + if (rule->src.seq.codes[i] != GREF (ctx->in, from + i)->c) + break; + if (i < len) + return 0; + to = from + len; + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT3 ("\n [FLT] %*s(SEQ 0x%X", depth, "", + rule->src.seq.codes[0]); + need_cluster_update = 1; + } + else if (rule->src_type == SRC_RANGE) + { + int head; + + if (from >= to) + return 0; + head = GREF (ctx->in, from)->c; + if (head < rule->src.range.from || head > rule->src.range.to) + return 0; + ctx->code_offset = head - rule->src.range.from; + to = from + 1; + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT4 ("\n [FLT] %*s(RANGE 0x%X-0x%X", depth, "", + rule->src.range.from, rule->src.range.to); + need_cluster_update = 1; + } + else if (rule->src_type == SRC_INDEX) + { + if (rule->src.match_idx >= NMATCH) + return 0; + from = ctx->match_indices[rule->src.match_idx * 2]; + if (from < 0) + return 0; + to = ctx->match_indices[rule->src.match_idx * 2 + 1]; + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT3 ("\n [FLT] %*s(SUBPART %d", depth, "", + rule->src.match_idx); + need_cluster_update = 1; + } + else if (rule->src_type == SRC_HAS_GLYPH + || rule->src_type == SRC_OTF_SPEC) + { + static MFLTGlyphString gstring; + MPlist *p; + int idx; + + if (rule->src.facility.len > 0) + { + if (! gstring.glyph_size) + { + gstring.glyph_size = ctx->in->glyph_size; + gstring.glyphs = calloc (rule->src.facility.len, + gstring.glyph_size); + gstring.allocated = rule->src.facility.len; + gstring.used = rule->src.facility.len; + } + else if (rule->src.facility.len < gstring.allocated) + { + gstring.glyphs = realloc (gstring.glyphs, + gstring.glyph_size + * rule->src.facility.len); + gstring.allocated = rule->src.facility.len; + gstring.used = rule->src.facility.len; + } + + for (i = 0, p = rule->src.facility.codes, idx = from; + i < rule->src.facility.len; i++, p = MPLIST_NEXT (p)) + { + if (MPLIST_INTEGER_P (p)) + { + GREF (&gstring, i)->c = MPLIST_INTEGER (p); + GREF (&gstring, i)->encoded = 0; + } + else + { + GREF (&gstring, i)->c = GREF (ctx->in, idx)->code; + GREF (&gstring, i)->encoded = GREF (ctx->in, idx)->encoded; + idx++; + } + } + } + + if (MDEBUG_FLAG () > 2) + { + if (rule->src_type == SRC_HAS_GLYPH) + MDEBUG_PRINT2 ("\n [FLT] %*s(HAS-GLYPH", depth, ""); + else + MDEBUG_PRINT2 ("\n [FLT] %*s(OTF-SPEC", depth, ""); + for (i = 0; i < rule->src.facility.len; i++) + MDEBUG_PRINT1 (" %04X", GREF (&gstring, i)->code); + } + if (ctx->font->get_glyph_id (ctx->font, &gstring, 0, + rule->src.facility.len) < 0) + { + MDEBUG_PRINT (") FAIL!"); + return 0; + } + if (rule->src_type == SRC_OTF_SPEC) + { + MFLTOtfSpec *spec = &rule->src.facility.otf_spec; + + if (! ctx->font->check_otf) + { + if ((spec->features[0] && spec->features[0][0] != 0xFFFFFFFF) + || (spec->features[1] && spec->features[1][0] != 0xFFFFFFFF)) + return 0; + } + else + { + if (rule->src.facility.len == 0) + { + if (! ctx->font->check_otf (ctx->font, spec)) + return 0; + } + else + { + int prev_out_used = ctx->out->used, out_used; + MFLTGlyphAdjustment *adjustment; + + adjustment = alloca ((sizeof *adjustment) + * (ctx->out->allocated - ctx->out->used)); + if (! adjustment) + MERROR (MERROR_FLT, -1); + memset (adjustment, 0, + (sizeof *adjustment) + * (ctx->out->allocated - ctx->out->used)); + ctx->font->drive_otf (ctx->font, &rule->src.facility.otf_spec, + &gstring, 0, rule->src.facility.len, + ctx->out, + adjustment); + out_used = ctx->out->used; + ctx->out->used = prev_out_used; + if (rule->src.facility.len == out_used - prev_out_used) + { + for (i = prev_out_used; i < out_used; i++) + { + if (GREF (&gstring, i - prev_out_used)->code + != GREF (ctx->out, i)->code) + break; + if (adjustment[i - prev_out_used].set) + break; + } + if (i == out_used) + return 0; + } + } + } + } + } + + if (need_cluster_update && ctx->cluster_begin_idx >= 0) + { + for (i = from; i < to; i++) + { + MFLTGlyph *g = GREF (ctx->in, i); + UPDATE_CLUSTER_RANGE (ctx, g); + } + } + + consumed = 0; + depth++; + for (i = 0; i < rule->n_cmds; i++) + { + int pos; + + if (rule->cmd_ids[i] == CMD_ID_REPEAT) + { + if (! consumed) + continue; + i--; + } + pos = run_command (depth, rule->cmd_ids[i], from, to, ctx); + if (pos < 0) + return pos; + consumed = pos > from; + if (consumed) + from = pos; + } + + ctx->match_indices = saved_match_indices; + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT (")"); + return (rule->src_type == SRC_INDEX ? orig_from : to); +} + +static int +run_cond (int depth, + FontLayoutCmdCond *cond, int from, int to, FontLayoutContext *ctx) +{ + int i, pos = 0; + + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT2 ("\n [FLT] %*s(COND", depth, ""); + depth++; + for (i = 0; i < cond->n_cmds; i++) + { + /* TODO: Write a code for optimization utilizaing the info + cond->seq_XXX. */ + if ((pos = run_command (depth, cond->cmd_ids[i], from, to, ctx)) + != 0) + break; + } + if (pos < 0) + return pos; + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT (")"); + return (pos); +} + +static void +decode_packed_otf_tag (FontLayoutContext *ctx, MFLTGlyphString *gstring, + int from, int to, FontLayoutCategory *category) +{ + for (; from < to; from++) + { + MFLTGlyph *g = GREF (gstring, from); + unsigned int tag = g->internal & 0xFFFFFFF; + char enc; + + if (GET_COMBINED (g)) + continue; + if (! category) + { + SET_CATEGORY_CODE (g, 0); + continue; + } + enc = '\0'; + if (tag & 0xFFFFF80) + { + int i; + + /* Clear the feature tag code. */ + g->internal &= ~0xFFFFFFF; + for (i = 0; i < category->feature_table.size; i++) + if (category->feature_table.tag[i] == tag) + { + enc = category->feature_table.code[i]; + if (ctx->in == gstring) + ctx->encoded[from - ctx->encoded_offset] = enc; + break; + } + } + if (! enc) + enc = (g->c > 0 ? (int) mchartable_lookup (category->table, g->c) + : g->c == 0 ? 1 : ' '); + SET_CATEGORY_CODE (g, enc); + } +} + +static int +run_otf (int depth, + MFLTOtfSpec *otf_spec, int from, int to, FontLayoutContext *ctx) +{ + MFLTFont *font = ctx->font; + int from_idx = ctx->out->used; + + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT3 ("\n [FLT] %*s%s", depth, "", MSYMBOL_NAME (otf_spec->sym)); + + font->get_glyph_id (font, ctx->in, from, to); + if (! font->drive_otf) + { + if (ctx->out->used + (to - from) > ctx->out->allocated) + return -2; + font->get_metrics (font, ctx->in, from, to); + GCPY (ctx->in, from, to - from, ctx->out, ctx->out->used); + ctx->out->used += to - from; + } + else + { + MFLTGlyphAdjustment *adjustment; + int out_len; + int i; + + adjustment = alloca ((sizeof *adjustment) + * (ctx->out->allocated - ctx->out->used)); + if (! adjustment) + MERROR (MERROR_FLT, -1); + memset (adjustment, 0, + (sizeof *adjustment) * (ctx->out->allocated - ctx->out->used)); + to = font->drive_otf (font, otf_spec, ctx->in, from, to, ctx->out, + adjustment); + if (to < 0) + return to; + decode_packed_otf_tag (ctx, ctx->out, from_idx, ctx->out->used, + ctx->category); + out_len = ctx->out->used - from_idx; + if (otf_spec->features[1]) + { + MFLTGlyphAdjustment *a; + MFLTGlyph *g; + + for (i = 0, a = adjustment; i < out_len; i++, a++) + if (a->set) + break; + if (i < out_len) + { + font->get_metrics (font, ctx->out, from_idx, ctx->out->used); + for (g = GREF (ctx->out, from_idx + i); + i < out_len; i++, a++, g = NEXT (ctx->out, g)) + if (a->set) + { + if (a->advance_is_absolute) + { + g->xadv = a->xadv; + g->yadv = a->yadv; + } + else if (a->xadv || a->yadv) + { + g->xadv += a->xadv; + g->yadv += a->yadv; + } + if (a->xoff || a->yoff || a->back) + { + int j; + MFLTGlyph *gg = PREV (ctx->out, g); + MFLTGlyphAdjustment *aa = a; + + g->xoff = a->xoff; + g->yoff = a->yoff; + g->lbearing += a->xoff; + g->rbearing += a->xoff; + g->ascent -= a->yoff; + g->descent -= a->yoff; + while (aa->back > 0) + { + for (j = 0; j < aa->back; + j++, gg = PREV (ctx->out, gg)) + { + g->xoff -= gg->xadv; + g->lbearing -= gg->xadv; + g->rbearing -= gg->xadv; + } + aa = aa - aa->back; + g->xoff += aa->xoff; + g->yoff += aa->yoff; + g->lbearing += aa->xoff; + g->rbearing += aa->xoff; + g->ascent -= aa->yoff; + g->descent -= aa->yoff; + } + } + g->adjusted = 1; + } + } + } + } + + if (ctx->cluster_begin_idx >= 0) + for (; from_idx < ctx->out->used; from_idx++) + { + MFLTGlyph *g = GREF (ctx->out, from_idx); + UPDATE_CLUSTER_RANGE (ctx, g); + } + return to; +} + +static int +try_otf (int depth, MFLTOtfSpec *otf_spec, int from, int to, + FontLayoutContext *ctx) +{ + MFLTFont *font = ctx->font; + + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT3 ("\n [FLT] %*s%s", depth, "", MSYMBOL_NAME (otf_spec->sym)); + + if (! otf_spec->features[0] && ! otf_spec->features[1]) + { + /* Reset categories. */ + MCharTable *table = ctx->category->table; + int i; + + for (i = from; i < to; i++) + { + MFLTGlyph *g = GREF (ctx->in, i); + + if (! GET_COMBINED (g)) + { + char enc = (GET_ENCODED (g) + ? (g->c > 0 ? (int) mchartable_lookup (table, g->c) + : 1) + : g->code + ? (int) mchartable_lookup (table, g->code) + : ' '); + SET_CATEGORY_CODE (g, enc); + ctx->encoded[i - ctx->encoded_offset] = enc; + } + } + return from; + } + + if (ctx->stage->category->feature_table.size == 0) + return from; + + font->get_glyph_id (font, ctx->in, from, to); + if (mflt_try_otf) + { + to = mflt_try_otf (font, otf_spec, ctx->in, from, to); + if (to < 0) + return from; + decode_packed_otf_tag (ctx, ctx->in, from, to, ctx->stage->category); + } + return from; +} + +static char work[16]; + +static char * +dump_combining_code (int code) +{ + char *vallign = "tcbB"; + char *hallign = "lcr"; + char *p; + int off_x, off_y; + + if (! code) + return "none"; + work[0] = vallign[COMBINING_CODE_BASE_Y (code)]; + work[1] = hallign[COMBINING_CODE_BASE_X (code)]; + off_y = COMBINING_CODE_OFF_Y (code); + off_x = COMBINING_CODE_OFF_X (code); + if (off_y > 0) + sprintf (work + 2, "+%d", off_y); + else if (off_y < 0) + sprintf (work + 2, "%d", off_y); + else if (off_x == 0) + sprintf (work + 2, "."); + p = work + strlen (work); + if (off_x > 0) + sprintf (p, ">%d", off_x); + else if (off_x < 0) + sprintf (p, "<%d", -off_x); + p += strlen (p); + p[0] = vallign[COMBINING_CODE_ADD_Y (code)]; + p[1] = hallign[COMBINING_CODE_ADD_X (code)]; + p[2] = '\0'; + return work; +} + +static int +run_command (int depth, int id, int from, int to, FontLayoutContext *ctx) +{ + MFLTGlyph *g; + + if (id >= 0) + { + int i; + MCharTable *table = ctx->category ? ctx->category->table : NULL; + char enc; + + /* Direct code (== ctx->code_offset + id) output. + The source is not consumed. */ + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT3 ("\n [FLT] %*s(DIRECT 0x%X", depth, "", + ctx->code_offset + id); + i = (from < to || from == 0) ? from : from - 1; + GDUP (ctx, i); + g = GREF (ctx->out, ctx->out->used - 1); + g->c = g->code = ctx->code_offset + id; + if (ctx->combining_code) + SET_COMBINING_CODE (g, ctx, ctx->combining_code); + else if (table) + { + enc = (GET_ENCODED (g) + ? (g->c > 0 ? (int) mchartable_lookup (table, g->c) : 1) + : g->code + ? (int) mchartable_lookup (table, g->code) + : ' '); + SET_CATEGORY_CODE (g, enc); + } + SET_ENCODED (g, 0); + SET_MEASURED (g, 0); + if (ctx->left_padding) + SET_LEFT_PADDING (g, ctx, LeftPaddingMask); + for (i = from; i < to; i++) + { + MFLTGlyph *tmp = GREF (ctx->in, i); + + if (g->from > tmp->from) + g->from = tmp->from; + else if (g->to < tmp->to) + g->to = tmp->to; + } + if (ctx->cluster_begin_idx >= 0) + UPDATE_CLUSTER_RANGE (ctx, g); + ctx->code_offset = ctx->combining_code = ctx->left_padding = 0; + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT (")"); + return (from); + } + + if (id <= CMD_ID_OFFSET_INDEX) + { + int idx = CMD_ID_TO_INDEX (id); + FontLayoutCmd *cmd; + + if (idx >= ctx->stage->used) + MERROR (MERROR_DRAW, -1); + cmd = ctx->stage->cmds + idx; + if (cmd->type == FontLayoutCmdTypeRule) + to = run_rule (depth, &cmd->body.rule, from, to, ctx); + else if (cmd->type == FontLayoutCmdTypeCond) + to = run_cond (depth, &cmd->body.cond, from, to, ctx); + else if (cmd->type == FontLayoutCmdTypeOTF) + to = run_otf (depth, &cmd->body.otf, from, to, ctx); + else if (cmd->type == FontLayoutCmdTypeOTFCategory) + to = try_otf (depth, &cmd->body.otf, from, to, ctx); + return to; + } + + if (id <= CMD_ID_OFFSET_COMBINING) + { + ctx->combining_code = CMD_ID_TO_COMBINING_CODE (id); + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT3 ("\n [FLT] %*s(CMB %s)", depth, "", + dump_combining_code (ctx->combining_code)); + return from; + } + + switch (id) + { + case CMD_ID_COPY: + { + if (from >= to) + return from; + GDUP (ctx, from); + g = GREF (ctx->out, ctx->out->used - 1); + if (ctx->combining_code) + SET_COMBINING_CODE (g, ctx, ctx->combining_code); + if (ctx->left_padding) + SET_LEFT_PADDING (g, ctx, LeftPaddingMask); + if (ctx->cluster_begin_idx >= 0) + UPDATE_CLUSTER_RANGE (ctx, g); + if (MDEBUG_FLAG () > 2) + { + if (g->c < 0) + MDEBUG_PRINT2 ("\n [FLT] %*s(COPY |)", depth, ""); + else + MDEBUG_PRINT3 ("\n [FLT] %*s(COPY 0x%X)", depth, "", g->c); + } + ctx->code_offset = ctx->combining_code = ctx->left_padding = 0; + return (from + 1); + } + + case CMD_ID_CLUSTER_BEGIN: + if (ctx->cluster_begin_idx < 0) + { + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT3 ("\n [FLT] %*s<%d", depth, "", + GREF (ctx->in, from)->from); + ctx->cluster_begin_idx = ctx->out->used; + ctx->cluster_begin_pos = GREF (ctx->in, from)->from; + ctx->cluster_end_pos = GREF (ctx->in, from)->to; + } + return from; + + case CMD_ID_CLUSTER_END: + if (ctx->cluster_begin_idx >= 0 + && ctx->cluster_begin_idx < ctx->out->used) + { + int i; + + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT1 (" %d>", ctx->cluster_end_pos + 1); + for (i = ctx->cluster_begin_idx; i < ctx->out->used; i++) + { + GREF (ctx->out, i)->from = ctx->cluster_begin_pos; + GREF (ctx->out, i)->to = ctx->cluster_end_pos; + } + ctx->cluster_begin_idx = -1; + } + return from; + + case CMD_ID_SEPARATOR: + { + int i; + + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT2 ("\n [FLT] %*s|", depth, ""); + i = from < to ? from : from - 1; + GDUP (ctx, i); + g = GREF (ctx->out, ctx->out->used - 1); + g->c = -1, g->code = 0; + g->xadv = g->yadv = 0; + SET_ENCODED (g, 1); + SET_MEASURED (g, 0); + SET_CATEGORY_CODE (g, ' '); + return from; + } + + case CMD_ID_LEFT_PADDING: + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT2 ("\n [FLT] %*s[", depth, ""); + ctx->left_padding = 1; + return from; + + case CMD_ID_RIGHT_PADDING: + if (ctx->out->used > 0) + { + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT2 ("\n [FLT] %*s]", depth, ""); + g = GREF (ctx->out, ctx->out->used - 1); + SET_RIGHT_PADDING (g, ctx, RightPaddingMask); + } + return from; + } + + MERROR (MERROR_DRAW, -1); +} + +static int +run_stages (MFLTGlyphString *gstring, int from, int to, + MFLT *flt, FontLayoutContext *ctx) +{ + MFLTGlyphString buf, *temp; + int stage_idx = 0; + int orig_from = from, orig_to = to; + int from_pos, to_pos, len; + int i, j; + MFLTGlyph *g; + MPlist *stages = flt->stages; + FontLayoutCategory *prev_category = NULL; + + from_pos = GREF (ctx->in, from)->from; + to_pos = GREF (ctx->in, to - 1)->to; + len = to_pos - from_pos + 1; + + buf = *(ctx->in); + buf.glyphs = NULL; + GINIT (ctx->out, ctx->out->allocated); + ctx->encoded = alloca (ctx->out->allocated); + if (! ctx->out->glyphs || ! ctx->encoded) + return -1; + + for (stage_idx = 0; 1; stage_idx++) + { + MCharTable *table; + int result; + + ctx->stage = (FontLayoutStage *) MPLIST_VAL (stages); + table = ctx->stage->category->table; + stages = MPLIST_NEXT (stages); + if (MPLIST_TAIL_P (stages)) + ctx->category = NULL; + else + ctx->category = ((FontLayoutStage *) MPLIST_VAL (stages))->category; + ctx->code_offset = ctx->combining_code = ctx->left_padding = 0; + ctx->encoded_offset = from; + for (i = from; i < to; i++) + { + MFLTGlyph *g = GREF (ctx->in, i); + char enc; + + if (GET_COMBINED (g) + || (prev_category && prev_category != ctx->stage->category)) + { + enc = (GET_ENCODED (g) + ? (g->c > 0 ? (int) mchartable_lookup (table, g->c) : 1) + : g->code + ? (int) mchartable_lookup (table, g->code) + : ' '); + if (! GET_COMBINED (g)) + SET_CATEGORY_CODE (g, enc); + } + else + enc = GET_CATEGORY_CODE (g); + ctx->encoded[i - from] = enc; + if (! enc && stage_idx == 0) + { + to = i; + break; + } + } + ctx->encoded[i - from] = '\0'; + ctx->match_indices[0] = from; + ctx->match_indices[1] = to; + for (i = 2; i < NMATCH; i++) + ctx->match_indices[i] = -1; + + if (MDEBUG_FLAG () > 2) + { + MDEBUG_PRINT2 ("\n [FLT] (STAGE %d \"%s\"", stage_idx, + ctx->encoded); + MDEBUG_PRINT (" ("); + for (i = from; i < to; i++) + { + g = GREF (ctx->in, i); + if (g->c == -1) + MDEBUG_PRINT2 ("%*s|", (i > 0), ""); + else + MDEBUG_PRINT3 ("%*s%04X", (i > 0), "", GREF (ctx->in, i)->code); + } + MDEBUG_PRINT (")"); + } + result = run_command (4, INDEX_TO_CMD_ID (0), from, to, ctx); + if (MDEBUG_FLAG () > 2) + MDEBUG_PRINT (")"); + if (result < 0) + return result; + + /* If this is the last stage, break the loop. */ + if (MPLIST_TAIL_P (stages)) + break; + + /* Otherwise, prepare for the next stage. */ + prev_category = ctx->stage->category; + temp = ctx->in; + ctx->in = ctx->out; + if (buf.glyphs) + ctx->out = temp; + else + { + GINIT (&buf, ctx->out->allocated); + ctx->out = &buf; + } + ctx->out->used = 0; + + from = 0; + to = ctx->in->used; + } + + if (ctx->out->used > 0) + { + /* Remove separator glyphs. */ + for (i = 0; i < ctx->out->used;) + { + g = GREF (ctx->out, i); + if (g->c < 0) + GREPLACE (NULL, 0, 0, ctx->out, i, i + 1); + else + i++; + } + } + if (ctx->out->used > 0) + { + int *g_indices; + int x_ppem = ctx->font->x_ppem << 6, y_ppem = ctx->font->y_ppem << 6; + + /* Get actual glyph IDs of glyphs. */ + ctx->font->get_glyph_id (ctx->font, ctx->out, 0, ctx->out->used); + + /* Check if all characters in the range are covered by some + glyph(s). If not, change and of glyphs to cover + uncovered characters. */ + g_indices = alloca (sizeof (int) * len); + if (! g_indices) + return -1; + for (i = 0; i < len; i++) g_indices[i] = -1; + for (i = 0; i < ctx->out->used; i++) + { + int pos; + + g = GREF (ctx->out, i); + for (pos = g->from; pos <= g->to; pos++) + if (g_indices[pos - from_pos] < 0) + g_indices[pos - from_pos] = i; + } + for (i = 0; i < len; i++) + if (g_indices[i] < 0) + { + if (i == 0) + { + int this_from; + + for (i++; i < len && g_indices[i] < 0; i++); + if (! (i < len)) + break; + j = g_indices[i]; + g = GREF (ctx->out, j); + this_from = g->from; + do { + g->from = orig_from + i; + } while (++j < ctx->out->used + && (g = GREF (ctx->out, j)) + && g->from == this_from); + } + else + { + int this_to; + + j = g_indices[i - 1]; + g = GREF (ctx->out, j); + this_to = g->to; + do { + g->to = orig_from + i + 1; + } while (--j >= 0 + && (g = GREF (ctx->out, j)) + && g->to == this_to); + } + } + + ctx->font->get_metrics (ctx->font, ctx->out, 0, ctx->out->used); + + /* Handle combining. */ + if (ctx->check_mask & CombinedMask) + { + MFLTGlyph *base = GREF (ctx->out, 0); + int base_height = base->ascent + base->descent; + int base_width = base->rbearing - base->lbearing; + int combining_code; + + for (i = 1; i < ctx->out->used; i++) + { + if ((g = GREF (ctx->out, i)) + && GET_COMBINED (g) + && (combining_code = GET_COMBINING_CODE (g))) + { + int height = g->ascent + g->descent; + int width = g->rbearing - g->lbearing; + int base_x, base_y, add_x, add_y, off_x, off_y; + + if (base->from > g->from) + base->from = g->from; + else if (base->to < g->to) + base->to = g->to; + + base_x = COMBINING_CODE_BASE_X (combining_code); + base_y = COMBINING_CODE_BASE_Y (combining_code); + add_x = COMBINING_CODE_ADD_X (combining_code); + add_y = COMBINING_CODE_ADD_Y (combining_code); + off_x = COMBINING_CODE_OFF_X (combining_code); + off_y = COMBINING_CODE_OFF_Y (combining_code); + + g->xoff = ((base_width * base_x - width * add_x) / 2 + + x_ppem * off_x / 100 + - (base->xadv - base->lbearing) - g->lbearing); + if (base_y < 3) + g->yoff = base_height * base_y / 2 - base->ascent; + else + g->yoff = 0; + if (add_y < 3) + g->yoff -= height * add_y / 2 - g->ascent; + g->yoff -= y_ppem * off_y / 100; + if (base->lbearing > base->xadv + g->lbearing + g->xoff) + base->lbearing = base->xadv + g->lbearing + g->xoff; + if (base->rbearing < base->xadv + g->rbearing + g->xoff) + base->rbearing = base->xadv + g->rbearing + g->xoff; + if (base->ascent < g->ascent - g->yoff) + base->ascent = g->ascent - g->yoff; + if (base->descent < g->descent - g->yoff) + base->descent = g->descent - g->yoff; + g->xadv = g->yadv = 0; + if (GET_RIGHT_PADDING (g)) + SET_RIGHT_PADDING (base, ctx, RightPaddingMask); + g->adjusted = 1; + } + else + { + base = g; + base_height = g->ascent + g->descent; + base_width = g->rbearing - g->lbearing; + } + } + } + + /* Handle padding */ + if (ctx->check_mask & (LeftPaddingMask | RightPaddingMask)) + for (i = 0; i < ctx->out->used; i++) + { + g = GREF (ctx->out, i); + if (! GET_COMBINED (g)) + { + if (GET_RIGHT_PADDING (g) && g->rbearing > g->xadv) + { + g->xadv = g->rbearing; + g->adjusted = 1; + } + if (GET_LEFT_PADDING (g) && g->lbearing < 0) + { + g->xoff += - g->lbearing; + g->xadv += - g->lbearing; + g->rbearing += - g->lbearing; + g->lbearing = 0; + g->adjusted = 1; + } + } + } + } + + GREPLACE (ctx->out, 0, ctx->out->used, gstring, orig_from, orig_to); + to = orig_from + ctx->out->used; + return to; +} + +static void +setup_combining_coverage (int from, int to, void *val, void *arg) +{ + int combining_class = (int) val; + int category = 0; + + if (combining_class < 200) + category = 'a'; + else if (combining_class <= 204) + { + if ((combining_class % 2) == 0) + category = "bcd"[(combining_class - 200) / 2]; + } + else if (combining_class <= 232) + { + if ((combining_class % 2) == 0) + category = "efghijklmnopq"[(combining_class - 208) / 2]; + } + else if (combining_class == 233) + category = 'r'; + else if (combining_class == 234) + category = 's'; + else if (combining_class == 240) + category = 't'; + mchartable_set_range ((MCharTable *) arg, from, to, (void *) category); +} + +static void +setup_combining_flt (MFLT *flt) +{ + MSymbol type; + MCharTable *combininig_class_table + = mchar_get_prop_table (Mcombining_class, &type); + + mchartable_set_range (flt->coverage->table, 0, 0x10FFFF, (void *) 'u'); + if (combininig_class_table) + mchartable_map (combininig_class_table, (void *) 0, + setup_combining_coverage, flt->coverage->table); +} + +#define CHECK_FLT_STAGES(flt) ((flt)->stages || load_flt (flt, NULL) == 0) + +static FontLayoutCategory * +configure_category (FontLayoutCategory *category, MFLTFont *font) +{ + if (! mflt_font_id || ! mflt_iterate_otf_feature) + { + FontLayoutCategory *new = malloc (sizeof (FontLayoutCategory)); + new->definition = NULL; + new->table = category->table; + M17N_OBJECT_REF (new->table); + return new; + } + return load_category_table (category->definition, font); +} + +static MFLT * +configure_flt (MFLT *flt, MFLTFont *font, MSymbol font_id) +{ + MPlist *plist; + MFLT *configured; + + if (! mflt_font_id || ! mflt_iterate_otf_feature) + return flt; + MPLIST_DO (plist, flt_list) + { + configured = MPLIST_VAL (plist); + if (! configured->font_id) + break; + if (configured->name == flt->name + && configured->font_id == font_id) + return configured; + } + if (! MSTRUCT_CALLOC_SAFE (configured)) + return flt; + *configured = *flt; + configured->stages = mplist_copy (flt->stages); + MPLIST_DO (plist, configured->stages) + { + FontLayoutStage *stage = MPLIST_VAL (plist); + if (stage->category->definition) + { + MSTRUCT_CALLOC (stage, MERROR_FLT); + *stage = *((FontLayoutStage *) MPLIST_VAL (plist)); + stage->category = configure_category (stage->category, font); + MPLIST_VAL (plist) = stage; + } + else + M17N_OBJECT_REF (stage->category->table); + } + configured->need_config = 0; + configured->font_id = font_id; + mplist_push (flt_list, flt->name, configured); + return configured; +} + +/* Internal API */ + +int m17n__flt_initialized; + + +/* External API */ + +/* The following two are actually not exposed to a user but concealed + by the macro M17N_INIT (). */ + +void +m17n_init_flt (void) +{ + int mdebug_flag = MDEBUG_INIT; + + merror_code = MERROR_NONE; + if (m17n__flt_initialized++) + return; + m17n_init_core (); + if (merror_code != MERROR_NONE) + { + m17n__flt_initialized--; + return; + } + + MDEBUG_PUSH_TIME (); + + Mcond = msymbol ("cond"); + Mrange = msymbol ("range"); + Mfont = msymbol ("font"); + Mlayouter = msymbol ("layouter"); + Mcombining = msymbol ("combining"); + Mfont_facility = msymbol ("font-facility"); + Mequal = msymbol ("="); + Mgenerator = msymbol ("generator"); + Mend = msymbol ("end"); + + mflt_enable_new_feature = 0; + mflt_iterate_otf_feature = NULL; + mflt_font_id = NULL; + mflt_try_otf = NULL; + + MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize the flt modules.")); + MDEBUG_POP_TIME (); +} + +void +m17n_fini_flt (void) +{ + int mdebug_flag = MDEBUG_FINI; + + if (m17n__flt_initialized == 0 + || --m17n__flt_initialized > 0) + return; + + MDEBUG_PUSH_TIME (); + free_flt_list (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize the flt modules.")); + MDEBUG_POP_TIME (); + m17n_fini_core (); +} + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + +/*** @addtogroup m17nFLT */ +/*** @{ */ +/*=*/ + +/*=*/ +/***en + @brief Return an FLT object that has a specified name. + + The mflt_get () function returns an FLT object whose name is $NAME. + + @return + If the operation was successful, mflt_get () returns a pointer + to the found FLT object. Otherwise, it returns @c NULL. */ + +/***ja + @brief ���ꤵ�줿̾������� FLT ���֥������Ȥ��֤�. + + �ؿ� mflt_get () �ϡ�$NAME �Ȥ���̾������� FLT ���֥������Ȥ��֤��� + + @return + �⤷��������С�mflt_get () �ϸ��Ĥ��ä� FLT + ���֥������ȤؤΥݥ��󥿤��֤������Ԥ������� @c NULL ���֤��� */ + +MFLT * +mflt_get (MSymbol name) +{ + MFLT *flt; + MPlist *plist; + + if (! flt_list && list_flt () < 0) + return NULL; + for (plist = flt_list; plist; plist = plist->next) + if (((MFLT *) MPLIST_VAL (plist))->font_id == Mnil) + break; + flt = mplist_get (plist, name); + if (! flt || ! CHECK_FLT_STAGES (flt)) + return NULL; + if (flt->name == Mcombining + && ! mchartable_lookup (flt->coverage->table, 0)) + setup_combining_flt (flt); + + return flt; +} + +/*=*/ +/***en + @brief Find an FLT suitable for the specified character and font. + + The mflt_find () function returns the most appropriate FLT for + layouting character $C with font $FONT. + + @return + If the operation was successful, mflt_find () returns a pointer + to the found FLT object. Otherwise, it returns @c NULL. */ + +/***ja + @brief ���ꤵ�줿ʸ���ȥե���Ȥ˹�ä� FLT ��õ��. + + �ؿ� mflt_find () �ϡ�ʸ�� $C ��ե���� $FONT + �ǥ쥤�����Ȥ��뤿��˺Ǥ�Ŭ�ڤ� FLT ���֤��� + + @return + �⤷��������С�mflt_find () �ϸ��Ĥ��ä� FLT + ���֥������ȤؤΥݥ��󥿤��֤������Ԥ������� @c NULL ���֤��� */ + +MFLT * +mflt_find (int c, MFLTFont *font) +{ + MPlist *plist, *pl; + MFLT *flt; + static MSymbol unicode_bmp = NULL, unicode_full = NULL; + + if (! unicode_bmp) + { + unicode_bmp = msymbol ("unicode-bmp"); + unicode_full = msymbol ("unicode-full"); + } + + if (! flt_list && list_flt () < 0) + return NULL; + /* Skip configured FLTs. */ + MPLIST_DO (plist, flt_list) + if (((MFLT *) MPLIST_VAL (plist))->font_id == Mnil) + break; + if (font) + { + MFLT *best = NULL; + + MPLIST_DO (pl, plist) + { + flt = MPLIST_VAL (pl); + if (flt->registry != unicode_bmp + && flt->registry != unicode_full) + continue; + if (flt->family && flt->family != font->family) + continue; + if (flt->name == Mcombining + && ! mchartable_lookup (flt->coverage->table, 0)) + setup_combining_flt (flt); + if (c >= 0 + && ! mchartable_lookup (flt->coverage->table, c)) + continue; + if (flt->otf.sym) + { + MFLTOtfSpec *spec = &flt->otf; + + if (! font->check_otf) + { + if ((spec->features[0] && spec->features[0][0] != 0xFFFFFFFF) + || (spec->features[1] && spec->features[1][0] != 0xFFFFFFFF)) + continue; + } + else if (! font->check_otf (font, spec)) + continue; + goto found; + } + best = flt; + } + if (best == NULL) + return NULL; + flt = best; + goto found; + } + if (c >= 0) + { + MPLIST_DO (pl, plist) + { + flt = MPLIST_VAL (pl); + if (mchartable_lookup (flt->coverage->table, c)) + goto found; + } + } + return NULL; + + found: + if (! CHECK_FLT_STAGES (flt)) + return NULL; + if (font && flt->need_config && mflt_font_id) + flt = configure_flt (flt, font, mflt_font_id (font)); + return flt; +} + +/*=*/ +/***en + @brief Return the name of an FLT. + + The mflt_name () function returns the name of $FLT. */ + +/***ja + @brief FLT ��̾�����֤�. + + �ؿ� mflt_name () �� $FLT ��̾�����֤��� */ + +const char * +mflt_name (MFLT *flt) +{ + return MSYMBOL_NAME (flt->name); +} + +/*=*/ +/***en + @brief Return a coverage of a FLT. + + The mflt_coverage () function returns a char-table that contains + nonzero values for characters supported by $FLT. */ + +/***ja + @brief FLT ���ϰϤ��֤�. + + �ؿ� mflt_coverage () �ϡ�$FLT �����ݡ��Ȥ���ʸ�����Ф��� + 0 �Ǥʤ��ͤ�ޤ�ʸ���ơ��֥���֤��� */ + +MCharTable * +mflt_coverage (MFLT *flt) +{ + return flt->coverage->table; +} + +/*=*/ +/***en + @brief Layout characters with an FLT. + + The mflt_run () function layouts characters in $GSTRING between + $FROM (inclusive) and $TO (exclusive) with $FONT. If $FLT is + nonzero, it is used for all the charaters. Otherwise, appropriate + FLTs are automatically chosen. + + @retval >=0 + The operation was successful. The value is the index to the + glyph, which was previously indexed by $TO, in $GSTRING->glyphs. + + @retval -2 + $GSTRING->glyphs is too short to store the result. The caller can + call this fucntion again with a longer $GSTRING->glyphs. + + @retval -1 + Some other error occurred. */ + +/***ja + @brief FLT ��Ȥä�ʸ����쥤�����Ȥ���. + + �ؿ� mflt_run () �ϡ�$GSTRING ��� $FROM ���� $TO ľ���ޤǤ�ʸ���� + $FONT ���Ѥ��ƥ쥤�����Ȥ��롣�⤷ $FLT + �������Ǥʤ���С������ͤ򤹤٤Ƥ�ʸ�����Ф����Ѥ��롣 + �����Ǥʤ����Ŭ�ڤ� FLT ��ưŪ�����򤹤롣 + + @retval >=0 + �¹������򼨤����֤�����ͤϡ�$GSTRING->glyphs ��ǰ��� $TO + �ˤ�äƼ�����Ƥ�������դؤΥ���ǥ����Ǥ��롣 + + @retval -2 + ��̤��Ǽ����ˤ� $GSTRING->glyphs ��û�����뤳�Ȥ򼨤��� + �ƤӽФ�¦�ϡ����Ĺ�� $GSTRING->glyphs + ���Ѥ��ƺ��٤��δؿ���Ƥ֤��Ȥ��Ǥ��롣 + + @retval -1 + ����¾�Υ��顼�����������Ȥ򼨤��� */ + +int +mflt_run (MFLTGlyphString *gstring, int from, int to, + MFLTFont *font, MFLT *flt) +{ + FontLayoutContext ctx; + int match_indices[NMATCH]; + MFLTGlyph *g; + MFLTGlyphString out; + int auto_flt = ! flt; + int c, i, j, k; + int this_from, this_to; + MSymbol font_id = mflt_font_id ? mflt_font_id (font) : Mnil; + + out = *gstring; + out.glyphs = NULL; + /* This is usually sufficient, but if not, we retry with the larger + values at most 3 times. This value is also used for the + allocating size of ctx.encoded. */ + out.allocated = (to - from) * 4; + + for (i = from; i < to; i++) + { + g = GREF (gstring, i); + if (! g->encoded) + { + c = g->c; + memset (g, 0, sizeof (MFLTGlyph)); + g->code = g->c = c; + } + g->from = g->to = i; + } + + for (this_from = from; this_from < to;) + { + if (! auto_flt) + { + for (this_to = this_from; this_to < to; this_to++) + if (mchartable_lookup (flt->coverage->table, + GREF (gstring, this_to)->c)) + break; + } + else + { + if (! flt_list && list_flt () < 0) + { + font->get_glyph_id (font, gstring, this_from, to); + font->get_metrics (font, gstring, this_from, to); + this_from = to; + break; + } + for (this_to = this_from; this_to < to; this_to++) + { + c = GREF (gstring, this_to)->c; + if (c >= flt_min_coverage && c <= flt_max_coverage) + break; + } + for (; this_to < to; this_to++) + { + c = GREF (gstring, this_to)->c; + if (font->internal + && mchartable_lookup (((MFLT *) font->internal)->coverage->table, c)) + { + flt = font->internal; + break; + } + flt = mflt_find (c, font); + if (flt) + { + if (CHECK_FLT_STAGES (flt)) + { + font->internal = flt; + break; + } + } + } + } + + if (this_from < this_to) + { + font->get_glyph_id (font, gstring, this_from, this_to); + font->get_metrics (font, gstring, this_from, this_to); + this_from = this_to; + } + if (this_to == to) + break; + + MDEBUG_PRINT1 (" [FLT] (%s", MSYMBOL_NAME (flt->name)); + + if (flt->need_config && font_id != Mnil) + flt = configure_flt (flt, font, font_id); + + for (; this_to < to; this_to++) + { + char enc; + g = GREF (gstring, this_to); + enc = (int) mchartable_lookup (flt->coverage->table, g->c); + if (! enc) + break; + SET_CATEGORY_CODE (g, enc); + } + + if (MDEBUG_FLAG ()) + { + if (font->family) + MDEBUG_PRINT1 (" (%s)", MSYMBOL_NAME (font->family)); + MDEBUG_PRINT ("\n [FLT] (SOURCE"); + for (i = this_from, j = 0; i < this_to; i++, j++) + { + if (j > 0 && j % 8 == 0) + MDEBUG_PRINT ("\n [FLT] "); + MDEBUG_PRINT1 (" %04X", GREF (gstring, i)->c); + } + MDEBUG_PRINT (")"); + } + + for (i = 0; i < 3; i++) + { + /* Setup CTX. */ + memset (&ctx, 0, sizeof ctx); + ctx.match_indices = match_indices; + ctx.font = font; + ctx.cluster_begin_idx = -1; + ctx.in = gstring; + ctx.out = &out; + j = run_stages (gstring, this_from, this_to, flt, &ctx); + if (j != -2) + break; + out.allocated *= 2; + } + + if (j < 0) + return j; + + to += j - this_to; + this_to = j; + + if (MDEBUG_FLAG ()) + { + MDEBUG_PRINT ("\n [FLT] (RESULT"); + if (MDEBUG_FLAG () > 1) + { + int idx = -1; + for (i = 0; this_from < this_to; i++, this_from++) + { + g = GREF (gstring, this_from); + if (g->from != idx) + { + if (i > 0) + MDEBUG_PRINT2 ("\n [FLT] %02d-%02d", + g->from, g->to); + else + MDEBUG_PRINT2 (" %02d-%02d", g->from, g->to); + idx = g->from; + } + MDEBUG_PRINT4 (" (%04X %d %d %d)", + g->code, g->xadv, g->xoff, g->yoff); + } + } + else + for (; this_from < this_to; this_from++) + MDEBUG_PRINT1 (" %04X", GREF (gstring, this_from)->code); + MDEBUG_PRINT ("))\n"); + } + this_from = this_to; + } + + if (gstring->r2l) + { + int len = to - from; + + GINIT (&out, len); + memcpy (((char *) out.glyphs), + ((char *) gstring->glyphs) + gstring->glyph_size * from, + gstring->glyph_size * len); + for (i = from, j = to; i < to;) + { + for (k = i + 1, j--; k < to && GREF (&out, k)->xadv == 0; + k++, j--); + GCPY (&out, i, (k - i), gstring, j); + i = k; + } + } + + return to; +} + +/***en + @brief Flag to control several new OTF handling commands. + + If the variable mflt_enable_new_feature is nonzero, the function + #mflt_run () can drive a Font Layout Table that contains the new + OTF-related commands ":otf?" and/or OTF feature specification in a + category table. */ +int mflt_enable_new_feature; + +int (*mflt_iterate_otf_feature) (struct _MFLTFont *font, + MFLTOtfSpec *spec, + int from, int to, + unsigned char *table); + +MSymbol (*mflt_font_id) (struct _MFLTFont *font); + +int (*mflt_try_otf) (struct _MFLTFont *font, MFLTOtfSpec *spec, + MFLTGlyphString *gstring, int from, int to); + + +/* for debugging... */ + +static void +dump_flt_cmd (FontLayoutStage *stage, int id, int indent) +{ + char *prefix = (char *) alloca (indent + 1); + + memset (prefix, 32, indent); + prefix[indent] = 0; + + if (id >= 0) + fprintf (mdebug__output, "0x%02X", id); + else if (id <= CMD_ID_OFFSET_INDEX) + { + int idx = CMD_ID_TO_INDEX (id); + FontLayoutCmd *cmd = stage->cmds + idx; + + if (cmd->type == FontLayoutCmdTypeRule) + { + FontLayoutCmdRule *rule = &cmd->body.rule; + int i; + + fprintf (mdebug__output, "(rule "); + if (rule->src_type == SRC_REGEX) + fprintf (mdebug__output, "\"%s\"", rule->src.re.pattern); + else if (rule->src_type == SRC_INDEX) + fprintf (mdebug__output, "%d", rule->src.match_idx); + else if (rule->src_type == SRC_SEQ) + fprintf (mdebug__output, "(seq)"); + else if (rule->src_type == SRC_RANGE) + fprintf (mdebug__output, "(range)"); + else + fprintf (mdebug__output, "(invalid src)"); + + for (i = 0; i < rule->n_cmds; i++) + { + fprintf (mdebug__output, "\n%s ", prefix); + dump_flt_cmd (stage, rule->cmd_ids[i], indent + 2); + } + fprintf (mdebug__output, ")"); + } + else if (cmd->type == FontLayoutCmdTypeCond) + { + FontLayoutCmdCond *cond = &cmd->body.cond; + int i; + + fprintf (mdebug__output, "(cond"); + for (i = 0; i < cond->n_cmds; i++) + { + fprintf (mdebug__output, "\n%s ", prefix); + dump_flt_cmd (stage, cond->cmd_ids[i], indent + 2); + } + fprintf (mdebug__output, ")"); + } + else if (cmd->type == FontLayoutCmdTypeOTF) + { + fprintf (mdebug__output, "(otf)"); + } + else + fprintf (mdebug__output, "(error-command)"); + } + else if (id <= CMD_ID_OFFSET_COMBINING) + fprintf (mdebug__output, "cominging-code"); + else + fprintf (mdebug__output, "(predefiend %d)", id); +} + +/***en + @brief Dump a Font Layout Table. + + The mdebug_dump_flt () function prints the Font Layout Table $FLT + in a human readable way to the stderr or to what specified by the + environment variable MDEBUG_OUTPUT_FILE. $INDENT specifies how + many columns to indent the lines but the first one. + + @return + This function returns $FLT. */ + +MFLT * +mdebug_dump_flt (MFLT *flt, int indent) +{ + char *prefix = (char *) alloca (indent + 1); + MPlist *plist; + int stage_idx = 0; + + memset (prefix, 32, indent); + prefix[indent] = 0; + fprintf (mdebug__output, "(flt"); + MPLIST_DO (plist, flt->stages) + { + FontLayoutStage *stage = (FontLayoutStage *) MPLIST_VAL (plist); + int i; + + fprintf (mdebug__output, "\n%s (stage %d", prefix, stage_idx); + for (i = 0; i < stage->used; i++) + { + fprintf (mdebug__output, "\n%s ", prefix); + dump_flt_cmd (stage, INDEX_TO_CMD_ID (i), indent + 4); + } + fprintf (mdebug__output, ")"); + stage_idx++; + } + fprintf (mdebug__output, ")"); + return flt; +} + +/***en + @brief Dump an MFLTGlyphString. + + The mflt_dump_gstring () function prints the glyph sequence + $GSTRING in a human readable way to the stderr or to what + specified by the environment variable MDEBUG_OUTPUT_FILE. */ + +void +mflt_dump_gstring (MFLTGlyphString *gstring) +{ + int i; + + fprintf (mdebug__output, "(flt-gstring"); + for (i = 0; i < gstring->used; i++) + { + MFLTGlyph *g = GREF (gstring, i); + fprintf (mdebug__output, "\n (%02d pos:%d-%d c:%04X code:%04X cat:%c)", + i, g->from, g->to, g->c, g->code, GET_CATEGORY_CODE (g)); + } + fprintf (mdebug__output, ")\n"); +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/m17n-flt.h b/src/m17n-flt.h new file mode 100644 index 0000000..5d1cefe --- /dev/null +++ b/src/m17n-flt.h @@ -0,0 +1,453 @@ +/* m17n-flt.h -- header file for the FLT API of the m17n library. + Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_FLT_H_ +#define _M17N_FLT_H_ + +#ifndef _M17N_CORE_H_ +#include +#endif + +M17N_BEGIN_HEADER + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) + +extern void m17n_init_flt (void); +#undef M17N_INIT +#ifdef _M17N_H_ +#define M17N_INIT() \ + do { \ + m17n_init (); \ + if (merror_code == MERROR_NONE) \ + m17n_init_flt (); \ + } while (0) +#else /* not _M17N_H_ */ +#define M17N_INIT() m17n_init_flt () +#endif /* not _M17N_H_ */ + +extern void m17n_fini_flt (void); +#undef M17N_FINI +#ifdef _M17N_H_ +#define M17N_FINI() \ + do { \ + m17n_fini_flt (); \ + m17n_fini (); \ + } while (0) +#else /* not _M17N_H_ */ +#define M17N_FINI() m17n_fini_flt () +#endif /* not _M17N_H_ */ + +#endif + +/***en @defgroup m17nFLT FLT API + @brief API provided by libm17n-flt.so */ +/***ja @defgroup m17nFLT FLT API + @brief libm17n-flt.so ���󶡤��� API */ +/*=*/ + +/*** @addtogroup m17nFLT */ +/*** @{ */ +/*=*/ + +/***en + @brief Type of information about a glyph. + + The type #MFLTGlyph is the structure that contains information + about a glyph. The members @ref c and @ref encoded are the + members to be set appropriately before calling the functions + mflt_find () and mflt_run (). And, if @ref encoded is set to 1, + the member @ref code should also be set. */ + +/***ja + @brief ����դ˴ؤ������η�. + + �� #MFLTGlyph �ϡ�����դ˴ؤ��������Ǽ���빽¤�ΤǤ��롣�ؿ� + mflt_find () �� mflt_run () ��Ƥ����ˤϥ��С� \ �� + \ ��Ŭ�ڤ����ꤷ�Ƥ����ͤФʤ餺���⤷ \ �� 1 + �Ȥ������� \ �����ꤷ�Ƥ����ͤФʤ�ʤ��� */ + +typedef struct +{ + /***en Character code (Unicode) of the glyph. */ + /***ja ����դ� (Unicode �ˤ�����) ʸ�������ɡ� */ + int c; + /***en Glyph ID of the glyph in the font. */ + /***ja �ե������ˤ����뤽�Υ���դ� ID�� */ + unsigned int code; + /***en Starting index of the run in #MFLTGlyphString that is + replaced by this glyph. */ + /***ja #MFLTGlyphString + ����ǡ����Υ���դˤ�ä��֤�����������ʬ����Ƭ�Υ���ǥ����� */ + int from; + /***en Ending index of the run in #MFLTGlyphString that is + replaced by this glyph. */ + /***ja #MFLTGlyphString + ����ǡ����Υ���դˤ�ä��֤�����������ʬ�������Υ���ǥ����� */ + int to; + /***en Advance width for horizontal layout expressed in 26.6 + fractional pixel format. */ + /***ja ���񤭻����������� 26.6 fractional pixel format ��ɽ��������Ρ� */ + int xadv; + /***en Advance height for vertical layout expressed in 26.6 + fractional pixel format. */ + /***ja �Ľ񤭻��������� 26.6 fractional pixel format ��ɽ��������Ρ� */ + int yadv; + /* @{ */ + /***en Ink metrics of the glyph expressed in 26.6 fractional pixel + format. */ + /***ja ���Υ���դΥ��󥯥�ȥ�å��� 26.6 fractional pixel format + ��ɽ��������Ρ� */ + int ascent, descent, lbearing, rbearing; + /* @} */ + /* @{ */ + /***en Horizontal and vertical adjustments for the glyph positioning + expressed in 26.6 fractional pixel format. */ + /***ja ����հ��ַ��κݤο�ʿ����ľĴ���ͤ� + 26.6 fractional pixel format ��ɽ��������Ρ� */ + int xoff, yoff; + /* @} */ + /***en Flag to tell whether the member \ has already been set + to a glyph ID in the font. */ + /***ja ���С� \ �˴��˥���� ID + �����åȤ���Ƥ��뤫�ݤ��򼨤��ե饰�� */ + unsigned encoded : 1; + /***en Flag to tell if the metrics of the glyph (members \ thru + \) are already calculated. */ + /***ja ���С� \ ���� \ + �ޤǤγƥ�ȥ�å������˷׻��Ѥ��ݤ��򼨤��ե饰�� */ + unsigned measured : 1; + /***en Flag to tell if the metrics of the glyph is adjusted, + i.e. \ or \ is different from the normal size, or + \ or \ is nonzero. */ + /***ja ����դΥ�ȥ�å���Ĵ���Ѥߤ��ݤ��� + ���ʤ���ʲ��Τ���1�İʾ夬��Ω���Ƥ��뤳�Ȥ򼨤��ե饰�� + \ ��ɸ����ͤȰۤʤ롢 + \ ��ɸ����ͤȰۤʤ롢 + \ �������Ǥʤ��� + \ �������Ǥʤ��� */ + unsigned adjusted : 1; + /***en For m17n-lib's internal use only. */ + /***ja m17n-lib ��������ѡ� */ + unsigned internal : 30; + + /* Arbitrary data can follow. */ +} MFLTGlyph; + +/*=*/ + +/***en + @brief Type of information about a glyph position adjustment. + + The type #MFLTGlyphAdjustment is the structure to store + information about a glyph metrics/position adjustment. It is + given to the callback function @b drive_otf of #MFLTFont. */ + +/***ja + @brief ����հ���Ĵ������Τ���η�. + + �� #MFLTGlyphAdjustment + �ϡ�����դΥ�ȥ�å�/���֤�Ĵ���˴ؤ��������Ǽ���뤿��ι�¤�ΤǤ��ꡢ + #MFLTFont �� callback �ؿ� @b drive_otf ���Ϥ���롣 */ + +typedef struct +{ + /* @{ */ + /***en Adjustments for advance width for horizontal layout and + advance height for vertical layout expressed in 26.6 fractional + pixel format. */ + /***ja ��ʿ����ľ�����������̤�Ĵ���ͤ� 26.6 fractional pixel format + ��ɽ��������Ρ� */ + int xadv, yadv; + /* @} */ + /* @{ */ + /***en Horizontal and vertical adjustments for glyph positioning + expressed in 26.6 fractional pixel format. */ + /***ja ����հ��ַ�᤿��ο�ʿ����ľĴ���ͤ� 26.6 fractional pixel + format ��ɽ��������Ρ� */ + int xoff, yoff; + /* @} */ + /***en Number of glyphs to go back for drawing a glyph. */ + /***ja ���������Τ�������٤�����տ��� */ + short back; + /***en If nonzero, the member \ and \ are absolute, i.e., + they should not be added to a glyph's origianl advance width and + height. */ + /***ja �󥼥��ΤȤ������С� \ �� \ �������ͤǤ��롣 + ���ʤ�������ͤ򥰥��������������˲û����ƤϤʤ�ʤ��� */ + unsigned advance_is_absolute : 1; + /***en Should be set to 1 iff at least one of the other members has + a nonzero value. */ + /***ja ¾�Υ��С��Τ�������1�Ĥ��󥼥��ΤȤ��Τߡ�1�˥��åȤ���롣 */ + unsigned set : 1; +} MFLTGlyphAdjustment; + +/*=*/ + +/***en + @brief Type of information about a glyph sequence. + + The type #MFLTGlyphString is the structure that contains + information about a sequence of glyphs. */ + +/***ja + @brief �������ξ���Τ���η�. + + �� #MFLTGlyphString �ϡ��������ξ�����Ǽ���뤿��ι�¤�ΤǤ��롣 */ + +typedef struct +{ + /***en The actual byte size of elements of the array pointed by the + member #glyphs. It must be equal to or greater than "sizeof + (MFLTGlyph)". */ + /***ja ���С� #glyphs �λؤ���������Ǥ�����¥Х��ȿ��� + �����ͤ� "sizeof (MFLTGlyph)" �ʾ�Ǥʤ���Фʤ�ʤ��� */ + int glyph_size; + /***en Array of glyphs. */ + /***ja ����դ����� */ + MFLTGlyph *glyphs; + /***en Number of elements allocated in #glyphs. */ + /***ja #glyphs ������֤���Ƥ������Ǥο��� */ + int allocated; + /***en Number of elements in #glyphs in use. */ + /***ja #glyphs ��ǻ���������Ǥο��� */ + int used; + /***en Flag to tell if the glyphs should be drawn from right-to-left + or not. */ + /***ja ����դ������麸�ؤ��������٤����ݤ��򼨤��ե饰�� */ + unsigned int r2l; +} MFLTGlyphString; + +/*=*/ + +/***en + @brief Type of specification of GSUB and GPOS OpenType tables. + + The type #MFLTOtfSpec is the structure that contains information + about the GSUB and GPOS features of a specific script and language + system. The information is used to select which features to + apply to a glyph string, or to check if a specific FLT is usable + for a specific font. */ + +/***ja + @brief GSUB ����� GPOS OpenType �ơ��֥�λ��ͤΤ���η�. + + �� #MFLTOtfSpec �ϡ�GSUB ����� GPOS�ե������㡼�ξ�����Ǽ���뤿 + ��ι�¤�ΤǤ��롣�����ե������㡼������Υ�����ץȤ���Ӹ��쥷 + ���ƥ�Τ�ΤǤ��롣���ξ���ϡ��ɤΥե������㡼�򥰥�����Ŭ�Ѥ� + �뤫�����뤤������� FLT ������Υե���Ȥ��Ф���ͭ�����ɤ����η��� + �˻��Ѥ���롣 */ + +typedef struct +{ + /***en Unique symbol representing the spec. This is the same as the + @ref OTF-SPEC of the FLT. */ + /***ja ���λ��ͤ�ɽ�魯��ˡ����ʥ���ܥ롣 + FLT �� @ref OTF-SPEC ��Ʊ����ͤǤ��롣 */ + MSymbol sym; + + /* @{ */ + /***en Tags for script and language system. */ + /***ja ������ץȤ���Ӹ��쥷���ƥ�Υ����� */ + unsigned int script, langsys; + /* @} */ + + /***en Array of GSUB (1st element) and GPOS (2nd element) feature + tag arrays. Each array is terminated by 0. It may be NULL if + there is no feature to specify. + + (1) The case of using this information for selecting which + features to apply to a glyph string. If the array is NULL, + apply no feature. If the first element is 0xFFFFFFFF, apply all + available features except for what appear in the second and + following elements (if any). Otherwise, apply all listed + features. + + (2) The case of using this information for checking if a a font + can be drived by a specific FLT. If the array is NULL, the font + should not have any features. Otherwize, the font should have + all features before 0xFFFFFFFF element (if any) and should not + have any features after that element. */ + /***ja GSUB �ե������㡼�������������1���ǡ�GPOS �ե������㡼������ + �������2���ǤȤ������󡣳������������0�Ǽ�����롣�ե������㡼 + �λ��꤬1�Ĥ�ʤ����Ϥ�����������Ǥ� NULL �Ǥ�褤�� + + (1) ���ξ��󤬥�������Ŭ�Ѥ��٤��ե������㡼������˻Ȥ���� + �硣�⤷���󼫿Ȥ�NULL�ʤ顢�ɤΥե������㡼��Ŭ�Ѥ��ʤ����⤷�� + ������Ǥ� 0xFFFFFFFF �ʤ顢�����ܰʹߤΥե������㡼�ʤ⤷���� + �Сˤ�������٤Ƥ�Ŭ�Ѳ�ǽ�ʥե������㡼��Ŭ�Ѥ��롣����ʳ��ξ� + ��ꥹ�Ȥ��줿���٤ƤΥե������㡼��Ŭ�Ѥ��롣 + + (2) ���ξ�������� FLT ������Υե���Ȥ�ͭ�����ɤ����η���˻� + �����硣�⤷���󼫿Ȥ�NULL�ʤ顢�ե���Ȥϥե������㡼���� + ����äƤ��ƤϤ����ʤ����⤷�ǽ�����Ǥ�0xFFFFFFFF�ʤ顢�ե���� + �ϣ����ܤ����ǰʹߤΥե���Ȥ���äƤ��ƤϤ����ʤ�������ʳ��ξ� + �硢�ե���Ȥ�0xFFFFFFFF �����Τ��٤ƤΥե������㡼����������� + 0xFFFFFFFF �ʹߤΥե������㡼�ϰ�Ĥ���äƤ��ƤϤ����ʤ���*/ + unsigned int *features[2]; +} MFLTOtfSpec; + +/*=*/ + +/***en + @brief Type of font to be used by the FLT driver. + + The type #MFLTFont is the structure that contains information + about a font used by the FLT driver. Usually, an application + should prepare a bigger structure whose first element is MFLTFont + and has more information about the font that is used by callback + funcitons, and give that structure to mflt functions by coercing + it to MFLTFont. It is assured that callback functions can safely + coerce MFLTFont back to the original structure. */ + +/***ja + @brief FLT �ɥ饤�Ф��Ȥ��ե���Ȥη�. + + �� #MFLTFont �ϡ�FLT�ɥ饤�Ф��Ȥ��ե���Ȥ˴ؤ��������Ǽ���뤿 + ��ι�¤�ΤǤ��롣�̾異�ץꥱ�������Ϻǽ�����Ǥ� MFLTFont �ǡ� + �Ĥ�����Ǥ�callback�ؿ������Ѥ���ե���Ⱦ������ä�������礭�� + ��¤�Τ��Ѱդ�������� MFLTFont �� coerce ���� mflt �γƴؿ����Ϥ��� + ��callback�ؿ��� MFLTFont �򸵤ι�¤�Τ� coerce ��ľ�����Ȥ��Ǥ��� + ���Ȥ��ݾڤ���Ƥ��롣 */ + +typedef struct _MFLTFont +{ + /***en Family name of the font. It may be #Mnil if the family name + is not important in finding a Font Layout Table suitable for the + font (for instance, in the case that the font is an OpenType + font). */ + /***ja �ե���ȤΥե��ߥ꡼̾���ե���Ȥ�Ŭ���� FLT��õ���ݤ˽��פǤ� + ����� (���Ȥ��� OpenType�ե���Ȥξ��ʤ�) �ϡ�#Mnil �Ǥ褤�� */ + MSymbol family; + + /***en Horizontal font sizes in pixels per EM. */ + /***ja �ե���Ȥο�ʿ�������� pixels per EM ��ɽ��������Ρ� */ + int x_ppem; + /***en Vertical font sizes in pixels per EM. */ + /***ja �ե���Ȥο�ľ�������� pixels per EM ��ɽ��������Ρ� */ + int y_ppem; + + /***en Callback function to get glyph IDs for glyphs between FROM + (inclusive) and TO (exclusive) of GSTRING. If the member \ + of a glyph is zero, the member \ of that glyph is a character + code. The function must convert it to the glyph ID of FONT. */ + /***ja GSTRING ��� FROM ���� TO ľ���ޤǤγƥ���դ��б����륰��� + ID��������뤿��� callback �ؿ����⤷���륰��դΥ��С� + \�������ʤ�С����Υ���դΥ��С� \ ��ʸ�������ɤ� + ���롣���δؿ��Ϥ���ʸ�������ɤ� FONT �Υ���� ID���Ѵ����ʤ��Ƥ� + �ʤ�ʤ��� */ + int (*get_glyph_id) (struct _MFLTFont *font, MFLTGlyphString *gstring, + int from, int to); + + /***en Callback function to get metrics of glyphs between FROM + (inclusive) and TO (exclusive) of GSTRING. If the member \ + of a glyph is zero, the function must set the members \, \, + \, \, \, and \ of the glyph. */ + /***ja GSTRING ��� FROM ���� TOľ���ޤǤγƥ���դ��б������ȥ�� + ����������뤿��� callback �ؿ����⤷���륰��դΥ��С� + \�������ʤ�С����δؿ��Ϥ��Υ���դΥ��С� \, + \, \, \, \, ����� \�򥻥� + �Ȥ��ʤ���Фʤ�ʤ��� */ + int (*get_metrics) (struct _MFLTFont *font, MFLTGlyphString *gstring, + int from, int to); + + /***en Callback function to check if the font has OpenType GSUB/GPOS + features for a specific script/language. The function must + return 1, if the font satisfies SPEC, or 0. It must be + NULL if the font does not have OpenType tables. */ + /***ja �ե���Ȥ���������Υ�����ץ�/������Ф��� GSUB/GPOS + OpenType�ե������㡼����Ĥ��ݤ���Ĵ�٤� callback �ؿ������δؿ� + �ϥե���Ȥ�SPEC ���������Ȥ��� 1 �򡢤����Ǥʤ��Ȥ��� 0���֤��� + ����Фʤ�ʤ����ե���Ȥ� OpenType �ơ��֥������ʤ��Ȥ���NULL + �Ǥʤ���Фʤ�ʤ��� */ + int (*check_otf) (struct _MFLTFont *font, MFLTOtfSpec *spec); + + /***en Callback function to apply OpenType features in SPEC to glyphs + between FROM (inclusive) and TO (exclusive) of IN. The resulting + glyphs are appended to the tail of OUT. If OUT does not + have a room to store all the resulting glyphs, it must return -2. + It must be NULL if the font does not have OpenType tables. */ + /***ja IN ��� FROM ���� TO ľ���ޤǤγƥ���դ� SPEC��γ� OpenType + �ե������㡼��Ŭ�Ѥ��뤿��� callback �ؿ���Ŭ�ѷ�̤Υ������� + OUT ���������ɲä���롣OUT ��û���᤮�Ʒ�̤��ɲä��ڤ�ʤ���� + �� -2 ���֤��ʤ��ƤϤʤ�ʤ����ե���Ȥ� OpenType �ơ��֥����� + �ʤ����� NULL�Ǥʤ���Фʤ�ʤ��� */ + int (*drive_otf) (struct _MFLTFont *font, MFLTOtfSpec *spec, + MFLTGlyphString *in, int from, int to, + MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment); + + /***en For m17n-lib's internal use only. It should be initialized + to NULL. */ + /***ja m17n-lib ����������ѡ�NULL �˽��Ͳ�����롣 */ + void *internal; +} MFLTFont; + +/*=*/ + +/***en + @brief Type of FLT (Font Layout Table). + + The type #MFLT is for an FLT object. Its internal structure is + concealed from application programs. */ + +/***ja + @brief FLT (Font Layout Table) �η�. + + �� #MFLT �� FLT ���֥������ȤΤ���η��Ǥ��롣 + ����������¤�ϡ����ץꥱ�������ץ�����फ��ϱ��ä���Ƥ��롣 */ + +typedef struct _MFLT MFLT; + +extern MFLT *mflt_get (MSymbol name); + +extern MFLT *mflt_find (int c, MFLTFont *font); + +extern const char *mflt_name (MFLT *flt); + +extern MCharTable *mflt_coverage (MFLT *flt); + +extern int mflt_run (MFLTGlyphString *gstring, int from, int to, + MFLTFont *font, MFLT *flt); + +/*=*/ +/*** @} */ + +extern int mflt_enable_new_feature; + +extern MSymbol (*mflt_font_id) (MFLTFont *font); + +extern int (*mflt_iterate_otf_feature) (MFLTFont *font, + MFLTOtfSpec *spec, + int from, int to, + unsigned char *table); + +extern int (*mflt_try_otf) (struct _MFLTFont *font, MFLTOtfSpec *spec, + MFLTGlyphString *gstring, int from, int to); + +M17N_END_HEADER + +#endif /* _M17N_FLT_H_ */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/m17n-gd.c b/src/m17n-gd.c new file mode 100644 index 0000000..2a2aa99 --- /dev/null +++ b/src/m17n-gd.c @@ -0,0 +1,885 @@ +/* m17n-gd.c -- implementation of the GUI API on GD Library. + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include "config.h" + +#if defined (HAVE_FREETYPE) && defined (HAVE_GD) + +#include +#include +#include +#include +#include + +#include "m17n-gui.h" +#include "m17n-misc.h" +#include "internal.h" +#include "internal-gui.h" +#include "symbol.h" +#include "font.h" +#include "fontset.h" +#include "face.h" + +static MPlist *realized_fontset_list; +static MPlist *realized_font_list; +static MPlist *realized_face_list; + +/* The first element is for 256 color, the second for true color. */ +static gdImagePtr scratch_images[2]; + +enum ColorIndex + { + COLOR_NORMAL, + COLOR_INVERSE, + COLOR_HLINE, + COLOR_BOX_TOP, + COLOR_BOX_BOTTOM, + COLOR_BOX_LEFT, + COLOR_BOX_RIGHT, + COLOR_MAX + }; + +static MSymbol M_rgb; + +static void +read_rgb_txt () +{ + FILE *fp; + int r, g, b, i; + + /* At first, support HTML 4.0 color names. */ + msymbol_put (msymbol ("black"), M_rgb, (void *) 0x000000); + msymbol_put (msymbol ("silver"), M_rgb, (void *) 0xC0C0C0); + msymbol_put (msymbol ("gray"), M_rgb, (void *) 0x808080); + msymbol_put (msymbol ("white"), M_rgb, (void *) 0xFFFFFF); + msymbol_put (msymbol ("maroon"), M_rgb, (void *) 0x800000); + msymbol_put (msymbol ("red"), M_rgb, (void *) 0xFF0000); + msymbol_put (msymbol ("purple"), M_rgb, (void *) 0x800080); + msymbol_put (msymbol ("fuchsia"), M_rgb, (void *) 0xFF00FF); + msymbol_put (msymbol ("green"), M_rgb, (void *) 0x008000); + msymbol_put (msymbol ("lime"), M_rgb, (void *) 0x00FF00); + msymbol_put (msymbol ("olive"), M_rgb, (void *) 0x808000); + msymbol_put (msymbol ("yellow"), M_rgb, (void *) 0xFFFF00); + msymbol_put (msymbol ("navy"), M_rgb, (void *) 0x000080); + msymbol_put (msymbol ("blue"), M_rgb, (void *) 0x0000FF); + msymbol_put (msymbol ("teal"), M_rgb, (void *) 0x008080); + msymbol_put (msymbol ("aqua"), M_rgb, (void *) 0x00FFFF); + + { + char *rgb_path[] + = {"/usr/lib/X11/rgb.txt", "/usr/X11R6/lib/X11/rgb.txt", + "/etc/X11/rgb.txt" }; + + fp = NULL; + for (i = 0; i < (sizeof rgb_path) / (sizeof rgb_path[0]); i++) + if ((fp = fopen ("/usr/lib/X11/rgb.txt", "r"))) + break; + if (! fp) + return; + } + while (1) + { + char buf[256]; + int c, len; + + if ((c = getc (fp)) == EOF) + break; + if (c == '!') + { + while ((c = getc (fp)) != EOF && c != '\n'); + continue; + } + ungetc (c, fp); + if (fscanf (fp, "%d %d %d", &r, &g, &b) != 3) + break; + while ((c = getc (fp)) != EOF && isspace (c)); + if (c == EOF) + break; + buf[0] = c; + fgets (buf + 1, 255, fp); + len = strlen (buf); + for (i = 0; i < len; i++) + buf[i] = tolower (buf[i]); + if (buf[len - 1] == '\n') + buf[len - 1] = '\0'; + b |= (r << 16) | (g << 8); + msymbol_put (msymbol (buf), M_rgb, (void *) b); + } + fclose (fp); +} + + +static int +parse_color (MSymbol sym) +{ + char *name = MSYMBOL_NAME (sym); + unsigned r = 0x80, g = 0x80, b = 0x80; + int i; + + do { + if (strncmp (name , "rgb:", 4) == 0) + { + name += 4; + if (sscanf (name, "%x", &r) < 1) + break; + for (i = 0; *name != '/'; i++, name++); + r = (i == 1 ? ((r << 1) | r) : (r >> (i - 2))); + name++; + if (sscanf (name, "%x", &g) < 1) + break; + for (i = 0; *name != '/'; i++, name++); + g = (i == 1 ? ((g << 1) | g) : (g >> (i - 2))); + name += 4; + if (sscanf (name, "%x", &b) < 1) + break; + for (i = 0; *name; i++, name++); + b = (i == 1 ? ((b << 1) | b) : (b >> (i - 2))); + } + else if (*name == '#') + { + name++; + i = strlen (name); + if (i == 3) + { + if (sscanf (name, "%1x%1x%1x", &r, &g, &b) < 3) + break; + r <<= 4, g <<= 4, b <<= 4; + } + else if (i == 6) + { + if (sscanf (name, "%2x%2x%2x", &r, &g, &b) < 3) + break; + } + else if (i == 9) + { + if (sscanf (name, "%3x%3x%3x", &r, &g, &b) < 3) + break; + r >>= 1, g >>= 1, b >>= 1; + } + else if (i == 12) + { + if (sscanf (name, "%4x%4x%4x", &r, &g, &b) < 3) + break; + r >>= 2, g >>= 2, b >>= 2; + } + } + else + return (int) msymbol_get (sym, M_rgb); + } while (0); + + return ((r << 16) | (g << 8) | b); +} + + +static gdImagePtr +get_scrach_image (gdImagePtr img, int width, int height) +{ + int index; + gdImagePtr scratch; + +#if HAVE_GD == 1 + index = 0; +#else + index = img->trueColor ? 1 : 0; +#endif + scratch = scratch_images[index]; + + if (scratch) + { + if (scratch->sx <= width && scratch->sy <= height) + return scratch; + gdImageDestroy (scratch); + } +#if HAVE_GD > 1 + if (img->trueColor) + scratch = scratch_images[1] = gdImageCreateTrueColor (width, height); + else +#endif + scratch = scratch_images[0] = gdImageCreate (width, height); + return scratch; +} + +static int +intersect_rectangle (MDrawMetric *r1, MDrawMetric *r2, MDrawMetric *rect) +{ + *rect = *r1; + if (rect->x < r2->x) + rect->width -= (r2->x - rect->x), rect->x = r2->x; + if (rect->x + rect->width > r2->x + r2->width) + rect->width -= (r2->x + r2->width - rect->x - rect->width); + if (rect->y < r2->y) + rect->height -= (r2->y - rect->y), rect->y = r2->y; + if (rect->y + rect->height > r2->y + r2->height) + rect->height -= (r2->y + r2->height - rect->y - rect->height); + return 1; +} + + +#define INTERSECT_RECTANGLE(r1, r2, rect) \ + (((r1)->x + (r1->width) <= (r2)->x \ + || (r2)->x + (r2)->width <= (r1)->x \ + || (r1)->y + (r1->height) <= (r2)->y \ + || (r2)->y + (r2)->height <= (r1)->y) \ + ? 0 \ + : intersect_rectangle (r1, r2, rect)) + + +#define RESOLVE_COLOR(img, color) \ + gdImageColorResolve ((img), (color) >> 16, ((color) >> 8) & 0xFF, \ + (color) & 0xFF) + +static MRealizedFont *gd_font_open (MFrame *, MFont *, MFont *, + MRealizedFont *); +static void gd_render (MDrawWindow, int, int, MGlyphString *, + MGlyph *, MGlyph *, int, MDrawRegion); + +static MFontDriver gd_font_driver = + { NULL, gd_font_open, NULL, NULL, NULL, gd_render, NULL }; + +static MRealizedFont * +gd_font_open (MFrame *frame, MFont *font, MFont *spec, MRealizedFont *rfont) +{ + double size = font->size ? font->size : spec->size; + int reg = spec->property[MFONT_REGISTRY]; + MRealizedFont *new; + + if (rfont) + { + MRealizedFont *save = NULL; + + for (; rfont; rfont = rfont->next) + if (rfont->font == font + && (rfont->font->size ? rfont->font->size == size + : rfont->spec.size == size) + && rfont->spec.property[MFONT_REGISTRY] == reg) + { + if (! save) + save = rfont; + if (rfont->driver == &gd_font_driver) + return rfont; + } + rfont = save; + } + rfont = (mfont__ft_driver.open) (frame, font, spec, rfont); + if (! rfont) + return NULL; + M17N_OBJECT_REF (rfont->info); + MSTRUCT_CALLOC (new, MERROR_GD); + *new = *rfont; + new->driver = &gd_font_driver; + new->next = MPLIST_VAL (frame->realized_font_list); + MPLIST_VAL (frame->realized_font_list) = new; + return new; +} + +static void +gd_render (MDrawWindow win, int x, int y, + MGlyphString *gstring, MGlyph *from, MGlyph *to, + int reverse, MDrawRegion region) +{ + gdImagePtr img = (gdImagePtr) win; + FT_Face ft_face; + MRealizedFace *rface = from->rface; + FT_Int32 load_flags = FT_LOAD_RENDER; + int i, j; + int color, pixel; + int r, g, b; + + if (from == to) + return; + + /* It is assured that the all glyphs in the current range use the + same realized face. */ + ft_face = rface->rfont->fontp; + color = ((int *) rface->info)[reverse ? COLOR_INVERSE : COLOR_NORMAL]; + pixel = RESOLVE_COLOR (img, color); + + if (gstring->anti_alias) + r = color >> 16, g = (color >> 8) & 0xFF, b = color & 0xFF; + else + { +#ifdef FT_LOAD_TARGET_MONO + load_flags |= FT_LOAD_TARGET_MONO; +#else + load_flags |= FT_LOAD_MONOCHROME; +#endif + } + + for (; from < to; x += from++->g.xadv) + { + unsigned char *bmp; + int xoff, yoff; + int width, pitch; + + FT_Load_Glyph (ft_face, (FT_UInt) from->g.code, load_flags); + yoff = y - ft_face->glyph->bitmap_top + from->g.yoff; + bmp = ft_face->glyph->bitmap.buffer; + width = ft_face->glyph->bitmap.width; + pitch = ft_face->glyph->bitmap.pitch; + if (! gstring->anti_alias) + pitch *= 8; + if (width > pitch) + width = pitch; + + if (gstring->anti_alias) + for (i = 0; i < ft_face->glyph->bitmap.rows; + i++, bmp += ft_face->glyph->bitmap.pitch, yoff++) + { + xoff = x + ft_face->glyph->bitmap_left + from->g.xoff; + for (j = 0; j < width; j++, xoff++) + if (bmp[j] > 0) + { + int pixel1 = pixel; +#if HAVE_GD > 1 + int alpha = gdAlphaTransparent * (255 - bmp[j]) / 255; + + if (alpha > 0) + pixel1 = gdImageColorResolveAlpha (img, r, g, b, alpha); +#else + int f = bmp[j] >> 5; + + if (f < 7) + { + int r1, g1, b1, color1; + + pixel1 = gdImageGetPixel (img, xoff, yoff); + r1 = gdImageRed (img, pixel1); + g1 = gdImageGreen (img, pixel1); + b1 = gdImageBlue (img, pixel1); + color1 = ((((r * f + r1 * (7 - f)) / 7) << 16) + | (((g * f + g1 * (7 - f)) / 7) << 8) + | ((b * f + b1 * (7 - f)) / 7)); + pixel1 = RESOLVE_COLOR (img, color1); + } +#endif + gdImageSetPixel (img, xoff, yoff, pixel1); + } + } + else + for (i = 0; i < ft_face->glyph->bitmap.rows; + i++, bmp += ft_face->glyph->bitmap.pitch, yoff++) + { + xoff = x + ft_face->glyph->bitmap_left + from->g.xoff; + for (j = 0; j < width; j++, xoff++) + if (bmp[j / 8] & (1 << (7 - (j % 8)))) + gdImageSetPixel (img, xoff, yoff, pixel); + } + } +} + +static void +gd_close (MFrame *frame) +{ +} + +static void * +gd_get_prop (MFrame *frame, MSymbol key) +{ + return NULL; +} + +static void +gd_realize_face (MRealizedFace *rface) +{ + int *colors; + MFaceHLineProp *hline; + MFaceBoxProp *box; + MSymbol *props = (MSymbol *) rface->face.property; + + if (rface != rface->ascii_rface) + { + rface->info = rface->ascii_rface->info; + return; + } + colors = malloc (sizeof (int) * COLOR_MAX); + colors[COLOR_NORMAL] = parse_color (props[MFACE_FOREGROUND]); + colors[COLOR_INVERSE] = parse_color (props[MFACE_BACKGROUND]); + if (rface->face.property[MFACE_VIDEOMODE] == Mreverse) + { + colors[COLOR_HLINE] = colors[COLOR_NORMAL]; + colors[COLOR_NORMAL] = colors[COLOR_INVERSE]; + colors[COLOR_INVERSE] = colors[COLOR_HLINE]; + } + colors[COLOR_HLINE] = 0; + + hline = rface->hline; + if (hline) + { + if (hline->color) + colors[COLOR_HLINE] = parse_color (hline->color); + else + colors[COLOR_HLINE] = colors[COLOR_NORMAL]; + } + + box = rface->box; + if (box) + { + if (box->color_top) + colors[COLOR_BOX_TOP] = parse_color (box->color_top); + else + colors[COLOR_BOX_TOP] = colors[COLOR_NORMAL]; + + if (box->color_left && box->color_left != box->color_top) + colors[COLOR_BOX_LEFT] = parse_color (box->color_left); + else + colors[COLOR_BOX_LEFT] = colors[COLOR_BOX_TOP]; + + if (box->color_bottom && box->color_bottom != box->color_top) + colors[COLOR_BOX_BOTTOM] = parse_color (box->color_bottom); + else + colors[COLOR_BOX_BOTTOM] = colors[COLOR_BOX_TOP]; + + if (box->color_right && box->color_right != box->color_bottom) + colors[COLOR_BOX_RIGHT] = parse_color (box->color_right); + else + colors[COLOR_BOX_RIGHT] = colors[COLOR_BOX_BOTTOM]; + } + + rface->info = colors; +} + +static void +gd_free_realized_face (MRealizedFace *rface) +{ + free (rface->info); +} + +static void +gd_fill_space (MFrame *frame, MDrawWindow win, MRealizedFace *rface, + int reverse, + int x, int y, int width, int height, MDrawRegion region) +{ + gdImagePtr img = (gdImagePtr) win; + int *colors = rface->info; + int color = colors[reverse ? COLOR_NORMAL : COLOR_INVERSE]; + MPlist *region_list = region, *plist; + + color = RESOLVE_COLOR (img, color); + if (! region) + gdImageFilledRectangle (img, x, y, x + width - 1, y + height - 1, color); + else + { + MDrawMetric rect;; + + rect.x = x, rect.y = y, rect.width = width, rect.height = height; + MPLIST_DO (plist, region_list) + { + MDrawMetric *r = MPLIST_VAL (plist), new; + + if (INTERSECT_RECTANGLE (r, &rect, &new)) + gdImageFilledRectangle (img, new.x, new.y, new.x + new.width - 1, + new.y + new.height - 1, color); + } + } +} + +static void +gd_draw_empty_boxes (MDrawWindow win, int x, int y, + MGlyphString *gstring, MGlyph *from, MGlyph *to, + int reverse, MDrawRegion region) +{ + gdImagePtr img = (gdImagePtr) win; + int *colors = from->rface->info; + int color = colors[reverse ? COLOR_INVERSE : COLOR_NORMAL]; + MPlist *region_list = region, *plist; + int height; + + if (from == to) + return; + + color = RESOLVE_COLOR (img, color); + y -= gstring->ascent - 1; + height = gstring->ascent + gstring->descent - 2; + if (! region) + for (; from < to; x += from++->g.xadv) + gdImageRectangle (img, x, y, x + from->g.xadv - 2, y + height - 1, color); + else + { + gdImagePtr cpy; + MGlyph *g; + int width, x1; + + for (g = from, width = 0; g < to; width += g++->g.xadv); + cpy = get_scrach_image (img, width, height); + MPLIST_DO (plist, region_list) + { + MDrawMetric *rect = MPLIST_VAL (plist); + gdImageCopy (cpy, img, rect->x - x, rect->y - y, rect->x, rect->y, + rect->x + rect->width, rect->y + rect->height); + } + for (x1 = 0; from < to; x1 += from++->g.xadv) + gdImageRectangle (cpy, x1, 0, x1 + from->g.xadv - 2, height - 1, color); + MPLIST_DO (plist, region_list) + { + MDrawMetric *rect = MPLIST_VAL (plist); + gdImageCopy (img, cpy, rect->x, rect->y, rect->x - x, rect->y - y, + rect->x + rect->width, rect->y + rect->height); + } + } +} + + +static void +gd_draw_hline (MFrame *frame, MDrawWindow win, MGlyphString *gstring, + MRealizedFace *rface, int reverse, + int x, int y, int width, MDrawRegion region) +{ + enum MFaceHLineType type = rface->hline->type; + int height = rface->hline->width; + gdImagePtr img = (gdImagePtr) win; + int *colors = rface->info; + int color = colors[COLOR_HLINE]; + MPlist *region_list = region, *plist; + + color = RESOLVE_COLOR (img, color); + y = (type == MFACE_HLINE_BOTTOM + ? y + gstring->text_descent - height + : type == MFACE_HLINE_UNDER + ? y + 1 + : type == MFACE_HLINE_STRIKE_THROUGH + ? y - ((gstring->ascent + gstring->descent) / 2) + : y - gstring->text_ascent); + if (! region) + gdImageFilledRectangle (img, x, y, x + width - 1, y + height - 1, color); + else + { + MDrawMetric rect; + + rect.x = x, rect.y = y, rect.width = width, rect.height = height; + MPLIST_DO (plist, region_list) + { + MDrawMetric *r = MPLIST_VAL (plist), new; + + if (INTERSECT_RECTANGLE (r, &rect, &new)) + gdImageFilledRectangle (img, new.x, new.y, new.x + new.width - 1, + new.y + new.height - 1, color); + } + } +} + + +static void +gd_draw_box (MFrame *frame, MDrawWindow win, MGlyphString *gstring, + MGlyph *g, int x, int y, int width, MDrawRegion region) +{ + gdImagePtr img = (gdImagePtr) win; + int *colors = g->rface->info; + int color; + MRealizedFace *rface = g->rface; + MFaceBoxProp *box = rface->box; + MPlist *region_list = region, *plist; + int y0, y1; + int i; + + y0 = y - (gstring->text_ascent + + rface->box->inner_vmargin + rface->box->width); + y1 = y + (gstring->text_descent + + rface->box->inner_vmargin + rface->box->width - 1); + + if (region) + { + int height = y1 - y0; + gdImagePtr cpy; + + if (g->type == GLYPH_BOX) + width = g->g.xadv; + cpy = get_scrach_image (img, width, height); + MPLIST_DO (plist, region_list) + { + MDrawMetric *rect = MPLIST_VAL (plist); + gdImageCopy (cpy, img, rect->x - x, rect->y - y, rect->x, rect->y, + rect->x + rect->width, rect->y + rect->height); + } + gd_draw_box (frame, win, gstring, g, 0, y - y0, width, NULL); + MPLIST_DO (plist, region_list) + { + MDrawMetric *rect = MPLIST_VAL (plist); + gdImageCopy (img, cpy, rect->x, rect->y, rect->x - x, rect->y - y, + rect->x + rect->width, rect->y + rect->height); + } + return; + } + + if (g->type == GLYPH_BOX) + { + int x0, x1; + + if (g->left_padding) + x0 = x + box->outer_hmargin, x1 = x + g->g.xadv - 1; + else + x0 = x, x1 = x + g->g.xadv - box->outer_hmargin - 1; + + /* Draw the top side. */ + color = RESOLVE_COLOR (img, colors[COLOR_BOX_TOP]); + for (i = 0; i < box->width; i++) + gdImageLine (img, x0, y0 + i, x1, y0 + i, color); + + /* Draw the bottom side. */ + color = RESOLVE_COLOR (img, colors[COLOR_BOX_BOTTOM]); + for (i = 0; i < box->width; i++) + gdImageLine (img, x0, y1 - i, x1, y1 - i, color); + + if (g->left_padding > 0) + { + /* Draw the left side. */ + color = RESOLVE_COLOR (img, colors[COLOR_BOX_LEFT]); + for (i = 0; i < rface->box->width; i++) + gdImageLine (img, x0 + i, y0 + i, x0 + i, y1 - i, color); + } + else + { + /* Draw the right side. */ + color = RESOLVE_COLOR (img, colors[COLOR_BOX_RIGHT]); + for (i = 0; i < rface->box->width; i++) + gdImageLine (img, x1 - i, y0 + i, x1 - i, y1 - i, color); + } + + } + else + { + /* Draw the top side. */ + color = RESOLVE_COLOR (img, colors[COLOR_BOX_TOP]); + for (i = 0; i < box->width; i++) + gdImageLine (img, x, y0 + i, x + width - 1, y0 + i, color); + + /* Draw the bottom side. */ + color = RESOLVE_COLOR (img, colors[COLOR_BOX_BOTTOM]); + for (i = 0; i < box->width; i++) + gdImageLine (img, x, y1 - i, x + width - 1, y1 - i, color); + } +} + + +static MDrawRegion +gd_region_from_rect (MDrawMetric *rect) +{ + MDrawMetric *new; + MPlist *plist = mplist (); + + MSTRUCT_MALLOC (new, MERROR_GD); + *new = *rect; + mplist_add (plist, Mt, new); + return (MDrawRegion) plist; +} + +static void +gd_union_rect_with_region (MDrawRegion region, MDrawMetric *rect) +{ + MPlist *plist = (MPlist *) region; + MDrawMetric *r; + + MSTRUCT_MALLOC (r, MERROR_GD); + *r = *rect; + mplist_push (plist, Mt, r); +} + +static void +gd_intersect_region (MDrawRegion region1, MDrawRegion region2) +{ + MPlist *plist1 = (MPlist *) region1, *p1 = plist1; + MPlist *plist2 = (MPlist *) region2; + MPlist *p2; + MDrawMetric rect, *rect1, *rect2, *r; + + while (! MPLIST_TAIL_P (p1)) + { + rect1 = mplist_pop (p1); + MPLIST_DO (p2, plist2) + { + rect2 = MPLIST_VAL (p2); + if (INTERSECT_RECTANGLE (rect1, rect2, &rect)) + { + MSTRUCT_MALLOC (r, MERROR_GD); + *r = rect; + mplist_push (p1, Mt, r); + p1 = MPLIST_NEXT (p1); + } + } + free (rect1); + } +} + +static void +gd_region_add_rect (MDrawRegion region, MDrawMetric *rect) +{ + MPlist *plist = (MPlist *) region; + MDrawMetric *new; + + MSTRUCT_MALLOC (new, MERROR_GD); + *new = *rect; + mplist_push (plist, Mt, new); +} + +static void +gd_region_to_rect (MDrawRegion region, MDrawMetric *rect) +{ + MPlist *plist = (MPlist *) region; + MDrawMetric *r = MPLIST_VAL (plist); + int min_x = r->x, max_x = min_x + r->width; + int min_y = r->y, max_y = min_y + r->height; + + MPLIST_DO (plist, MPLIST_NEXT (plist)) + { + r = MPLIST_VAL (plist); + if (r->x < min_x) + min_x = r->x; + if (r->x + r->width > max_x) + max_x = r->x + r->width; + if (r->y < min_y) + min_y = r->y; + if (r->y + r->height > max_y) + max_y = r->y + r->height; + } + rect->x = min_x; + rect->y = min_y; + rect->width = max_x - min_x; + rect->height =max_y - min_y; +} + +static void +gd_free_region (MDrawRegion region) +{ + MPlist *plist = (MPlist *) region; + + MPLIST_DO (plist, plist) + free (MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (region); +} + +static void +gd_dump_region (MDrawRegion region) +{ + MDrawMetric rect; + + gd_region_to_rect (region, &rect); + fprintf (mdebug__output, "(%d %d %d %d)\n", + rect.x, rect.y, rect.width, rect.height); +} + +static MDeviceDriver gd_driver = + { + gd_close, + gd_get_prop, + gd_realize_face, + gd_free_realized_face, + gd_fill_space, + gd_draw_empty_boxes, + gd_draw_hline, + gd_draw_box, + NULL, + gd_region_from_rect, + gd_union_rect_with_region, + gd_intersect_region, + gd_region_add_rect, + gd_region_to_rect, + gd_free_region, + gd_dump_region, + }; + +/* Functions to be stored in MDeviceLibraryInterface by dlsym (). */ + +int +device_init () +{ + M_rgb = msymbol (" rgb"); + read_rgb_txt (); + realized_fontset_list = mplist (); + realized_font_list = mplist (); + realized_face_list = mplist (); + scratch_images[0] = scratch_images[1] = NULL; + + gd_font_driver.select = mfont__ft_driver.select; + gd_font_driver.find_metric = mfont__ft_driver.find_metric; + gd_font_driver.has_char = mfont__ft_driver.has_char; + gd_font_driver.encode_char = mfont__ft_driver.encode_char; + gd_font_driver.list = mfont__ft_driver.list; + gd_font_driver.check_otf = mfont__ft_driver.check_otf; + gd_font_driver.drive_otf = mfont__ft_driver.drive_otf; + + return 0; +} + +int +device_fini () +{ + MPlist *plist; + int i; + + MPLIST_DO (plist, realized_fontset_list) + mfont__free_realized_fontset ((MRealizedFontset *) MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (realized_fontset_list); + + MPLIST_DO (plist, realized_face_list) + { + MRealizedFace *rface = MPLIST_VAL (plist); + + free (rface->info); + mface__free_realized (rface); + } + M17N_OBJECT_UNREF (realized_face_list); + + if (MPLIST_VAL (realized_font_list)) + mfont__free_realized (MPLIST_VAL (realized_font_list)); + M17N_OBJECT_UNREF (realized_font_list); + + for (i = 0; i < 2; i++) + if (scratch_images[i]) + gdImageDestroy (scratch_images[i]); + return 0; +} + +int +device_open (MFrame *frame, MPlist *param) +{ + MFace *face; + + frame->device = NULL; + frame->device_type = MDEVICE_SUPPORT_OUTPUT; + frame->dpi = (int) mplist_get (param, Mresolution); + if (frame->dpi == 0) + frame->dpi = 100; + frame->driver = &gd_driver; + frame->font_driver_list = mplist (); + mplist_add (frame->font_driver_list, Mfreetype, &gd_font_driver); + frame->realized_font_list = realized_font_list; + frame->realized_face_list = realized_face_list; + frame->realized_fontset_list = realized_fontset_list; + face = mface_copy (mface__default); + mface_put_prop (face, Mfoundry, Mnil); + mface_put_prop (face, Mfamily, Mnil); + mplist_push (param, Mface, face); + M17N_OBJECT_UNREF (face); + return 0; +} + +#else /* not HAVE_GD nor HAVE_FREETYPE */ + +int device_open () { return -1; } + +#endif /* not HAVE_GD nor HAVE_FREETYPE */ + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ diff --git a/src/m17n-gui.c b/src/m17n-gui.c new file mode 100644 index 0000000..b7810e4 --- /dev/null +++ b/src/m17n-gui.c @@ -0,0 +1,824 @@ +/* m17n-gui.c -- body of the GUI API. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nGUI + @brief GUI support for a window system. + + This section defines the m17n GUI API concerning M-text drawing + and inputting under a window system. + + All the definitions here are independent of window systems. An + actual library file, however, can depend on a specific window + system. For instance, the library file m17n-X.so is an example of + implementation of the m17n GUI API for the X Window System. + + Actually the GUI API is mainly for toolkit libraries or to + implement XOM, not for direct use from application programs. +*/ + +/***ja + @addtogroup m17nGUI + @brief ������ɥ������ƥ��� GUI ���ݡ���. + + ���Υ��������ϥ�����ɥ������ƥ�Τ�ȤǤ� M-text ��ɽ�������Ϥˤ������ + m17n GUI API ��������롣 + + �����ǤΤ��٤Ƥ�����ϥ�����ɥ������ƥ�Ȥ���Ω�Ǥ��롣 + ���������ºݤΥ饤�֥��ե�����ϸ��̤Υ�����ɥ������ƥ�˰�¸�����礬���롣 + ���Ȥ��Х饤�֥��ե����� m17n-X.so �ϡ�m17n GUI API �� X + ������ɥ��Ѥμ�����Ǥ��롣 + + ���¤ˤϡ�GUI API �ϼ�˥ġ��륭�åȥ饤�֥������Ǥ��뤫���ޤ��� + XOM ��������뤿����Ѥ����Ƥ��ꡢ���ץꥱ�������ץ�����फ���ľ�ܤ����Ѥ�ǰƬ�ˤ�������ΤǤϤʤ��� +*/ + +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include "config.h" + +#include +#include +#include + +#include "config.h" +#ifdef HAVE_DLFCN_H +#include +#endif + +#include "m17n-gui.h" +#include "m17n-misc.h" +#include "internal.h" +#include "plist.h" +#include "internal-gui.h" +#include "font.h" +#include "fontset.h" +#include "face.h" + +#ifndef DLOPEN_SHLIB_EXT +#define DLOPEN_SHLIB_EXT ".so" +#endif + +/** Information about a dynamic library supporting a specific graphic + device. */ +typedef struct +{ + /** Name of the dynamic library (e.g. "libm17n-X.so"). */ + char *library; + /** Handle of the dynamic library. */ + void *handle; + /** Function to call just after loading the library. */ + int (*init) (); + /** Function to call to open a frame on the graphic device. */ + int (*open) (MFrame *frame, MPlist *param); + /** Function to call just before unloading the library. */ + int (*fini) (); +} MDeviceLibraryInterface; + + +/** Plist of device symbol vs MDeviceLibraryInterface. */ + +static MPlist *device_library_list; + +/** Close MFrame and free it. */ + +static void +free_frame (void *object) +{ + MFrame *frame = (MFrame *) object; + + (*frame->driver->close) (frame); + M17N_OBJECT_UNREF (frame->face); + M17N_OBJECT_UNREF (frame->font_driver_list); + free (object); +} + + +/** Register a dynamic library of name LIB by a key NAME. */ + +static int +register_device_library (MSymbol name, char *lib) +{ + MDeviceLibraryInterface *interface; + + MSTRUCT_CALLOC (interface, MERROR_WIN); + interface->library = malloc (strlen (M17N_MODULE_DIR) + 1 + + strlen (lib) + + strlen (DLOPEN_SHLIB_EXT) + 1); + sprintf (interface->library, "%s/%s%s", M17N_MODULE_DIR, lib, + DLOPEN_SHLIB_EXT); + if (! device_library_list) + device_library_list = mplist (); + mplist_add (device_library_list, name, interface); + return 0; +} + + +#ifdef HAVE_FREETYPE +/** Null device support. */ + +static struct { + MPlist *realized_fontset_list; + MPlist *realized_font_list; + MPlist *realized_face_list; +} null_device; + +static void +null_device_close (MFrame *frame) +{ +} + +static void * +null_device_get_prop (MFrame *frame, MSymbol key) +{ + return NULL; +} + +static void +null_device_realize_face (MRealizedFace *rface) +{ + rface->info = NULL; +} + +static void +null_device_free_realized_face (MRealizedFace *rface) +{ +} + +static MDeviceDriver null_driver = + { + null_device_close, + null_device_get_prop, + null_device_realize_face, + null_device_free_realized_face + }; + +static int +null_device_init () +{ + null_device.realized_fontset_list = mplist (); + null_device.realized_font_list = mplist (); + null_device.realized_face_list = mplist (); + return 0; +} + +static int +null_device_fini () +{ + MPlist *plist; + + MPLIST_DO (plist, null_device.realized_fontset_list) + mfont__free_realized_fontset ((MRealizedFontset *) MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (null_device.realized_fontset_list); + + MPLIST_DO (plist, null_device.realized_face_list) + mface__free_realized ((MRealizedFace *) MPLIST_VAL (plist)); + M17N_OBJECT_UNREF (null_device.realized_face_list); + + if (MPLIST_VAL (null_device.realized_font_list)) + mfont__free_realized (MPLIST_VAL (null_device.realized_font_list)); + M17N_OBJECT_UNREF (null_device.realized_font_list); + return 0; +} + +static int +null_device_open (MFrame *frame, MPlist *param) +{ + MFace *face; + + frame->device = NULL; + frame->device_type = 0; + frame->dpi = (int) mplist_get (param, Mresolution); + if (frame->dpi == 0) + frame->dpi = 100; + frame->driver = &null_driver; + frame->font_driver_list = mplist (); + mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver); + frame->realized_font_list = null_device.realized_font_list; + frame->realized_face_list = null_device.realized_face_list; + frame->realized_fontset_list = null_device.realized_fontset_list; + face = mface_copy (mface__default); + mplist_push (param, Mface, face); + M17N_OBJECT_UNREF (face); + return 0; +} + +static MDeviceLibraryInterface null_interface = + { NULL, NULL, null_device_init, null_device_open, null_device_fini }; + +#endif + +/* Internal API */ + + +/* External API */ + +void +m17n_init_win (void) +{ + int mdebug_flag = MDEBUG_INIT; + + merror_code = MERROR_NONE; + if (m17n__gui_initialized++) + return; + m17n_init (); + m17n_init_flt (); + if (merror_code != MERROR_NONE) + { + m17n__gui_initialized--; + return; + } + + MDEBUG_PUSH_TIME (); + + Mgd = msymbol ("gd"); + + Mfont = msymbol ("font"); + Mfont_width = msymbol ("font-width"); + Mfont_ascent = msymbol ("font-ascent"); + Mfont_descent = msymbol ("font-descent"); + Mdevice = msymbol ("device"); + + Mdisplay = msymbol ("display"); + Mscreen = msymbol ("screen"); + Mdrawable = msymbol ("drawable"); + Mdepth = msymbol ("depth"); + Mwidget = msymbol ("widget"); + Mcolormap = msymbol ("colormap"); + + MDEBUG_PUSH_TIME (); + if (mfont__init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize font module.")); + if (mfont__fontset_init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize fontset module.")); + if (mface__init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize face module.")); + if (mdraw__init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize draw module.")); + if (minput__win_init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", + (mdebug__output, " to initialize input-win module.")); + mframe_default = NULL; + + register_device_library (Mx, "libm17n-X"); + register_device_library (Mgd, "libm17n-gd"); + return; + + err: + MDEBUG_POP_TIME (); + MDEBUG_PRINT_TIME ("INIT", + (mdebug__output, " to initialize the m17n GUI module.")); + MDEBUG_POP_TIME (); +} + +void +m17n_fini_win (void) +{ + int mdebug_flag = MDEBUG_FINI; + MPlist *plist; + + if (m17n__gui_initialized == 0 + || --m17n__gui_initialized > 0) + return; + + MDEBUG_PUSH_TIME (); + MDEBUG_PUSH_TIME (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize device modules.")); + MPLIST_DO (plist, device_library_list) + { + MDeviceLibraryInterface *interface = MPLIST_VAL (plist); + + if (interface->handle && interface->fini) + { + (*interface->fini) (); + dlclose (interface->handle); + } + free (interface->library); + free (interface); + } +#ifdef HAVE_FREETYPE + if (null_interface.handle) + { + (*null_interface.fini) (); + null_interface.handle = NULL; + } +#endif /* not HAVE_FREETYPE */ + M17N_OBJECT_UNREF (device_library_list); + minput__win_fini (); + MDEBUG_PRINT_TIME ("FINI", + (mdebug__output, " to finalize input-gui module.")); + mdraw__fini (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize draw module.")); + mface__fini (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize face module.")); + mfont__fontset_fini (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize fontset module.")); + mfont__fini (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize font module.")); + mframe_default = NULL; + MDEBUG_POP_TIME (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize the gui modules.")); + MDEBUG_POP_TIME (); + m17n_fini_flt (); + m17n_fini (); +} + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + +/*** @addtogroup m17nFrame */ +/***en + @brief A @e frame is an object corresponding to the graphic device. + + A @e frame is an object of the type #MFrame to hold various + information about each display/input device. Almost all m17n GUI + functions require a pointer to a frame as an argument. */ +/***ja + @brief @e �ե졼�� �Ȥϥ���ե��å��ǥХ������б����륪�֥������ȤǤ���. + + @e �ե졼�� �Ȥ� #MFrame + ���Υ��֥������ȤǤ��ꡢ�ġ���ɽ�������ϥǥХ����ξ�����Ǽ���뤿����Ѥ����롣 + �ۤȤ�ɤ��٤Ƥ� m17n GUI�ؿ��ϡ������Ȥ��ƥե졼��ؤΥݥ��󥿤��׵᤹�롣 */ + +/*** @{ */ +/*=*/ + +/***en + @name Variables: Keys of frame parameter + + These are the symbols to use in a parameter to create a frame. See + the function mframe () for details. + + @b Mdevice, @b Mdisplay, @b Mscreen, @b Mdrawable, @b Mdepth, and + @b Mcolormap are also keys of a frame property. */ + +/***ja + @name �ѿ��� �ե졼��ѥ�᡼���ѥ��� + + �ե졼�����������ݤΥѥ�᡼�����Ѥ��륷��ܥ롣�ܤ����ϴؿ� + mframe () ���������ȡ� + + @b Mdevice�� @b Mdisplay�� @b Mscreen�� @b Mdrawable�� @b Mdepth�� + @b Mcolormap �ϥե졼��ץ��ѥƥ��Υ����Ǥ⤢�롣 */ + +/*=*/ + +MSymbol Mdevice, Mdisplay, Mscreen, Mdrawable, Mdepth, Mcolormap, Mwidget; + +MSymbol Mgd; + +/*=*/ + +/***en + @name Variables: Keys of frame property + + These are the symbols to use as an argument to the function + mframe_get_prop (). */ +/***ja + @name �ѿ��� �ե졼��ץ��ѥƥ��Υ��� + + �ؿ� mframe_get_prop () �ΰ������Ѥ����륷��ܥ롣 */ +/*** @{ */ +/*=*/ +MSymbol Mfont; +MSymbol Mfont_width; +MSymbol Mfont_ascent; +MSymbol Mfont_descent; + +/*=*/ + +/*** @} */ +/*=*/ + +/***en + @brief Create a new frame. + + The mframe () function creates a new frame with parameters listed + in $PLIST which may be @c NULL. + + The recognized keys in $PLIST are window system dependent. + + The following key is always recognized. + +
    + +
  • @b Mdevice, the value must be one of #Mx, @b Mgd, and #Mnil. + + If the value is #Mx, the frame is for X Window System. The + argument #MDrawWindow specified together with the frame must be of + type @c Window. The frame is both readable and writable, thus all + GUI functions can be used. + + If the value is @b Mgd, the frame is for an image object of GD + library. The argument #MDrawWindow specified together with the + frame must be of type @c gdImagePtr. The frame is writable + only, thus functions minput_XXX can't be used for the frame. + + If the value is #Mnil, the frame is for a null device. The frame + is not writable nor readable, thus functions mdraw_XXX that + require the argument #MDrawWindow and functions minput_XXX can't + be used for the frame. + +
  • #Mface, the value must be a pointer to #MFace. + + The value is used as the default face of the frame. + +
+ + In addition, if the value of the key @b Mdevice is #Mx, the + following keys are recognized. They are to specify the root + window and the depth of drawables that can be used with the frame. + +
    + +
  • @b Mdrawable, the value type must be Drawable. + + A parameter of key @b Mdisplay must also be specified. The + created frame can be used for drawables whose root window and + depth are the same as those of the specified drawable on the + specified display. + + When this parameter is specified, the parameter of key @b Mscreen + is ignored. + +
  • @b Mwidget, the value type must be Widget. + + The created frame can be used for drawables whose root window and + depth are the same as those of the specified widget. + + If a parameter of key #Mface is not specified, the default face + is created from the resources of the widget. + + When this parameter is specified, the parameters of key @b Mdisplay, + @b Mscreen, @b Mdrawable, @b Mdepth are ignored. + +
  • @b Mdepth, the value type must be unsigned. + + The created frame can be used for drawables of the specified + depth. + +
  • @b Mscreen, the value type must be (Screen *). + + The created frame can be used for drawables whose root window is + the same as the root window of the specified screen, and depth is + the same at the default depth of the screen. + + When this parameter is specified, parameter of key @b Mdisplay is + ignored. + +
  • @b Mdisplay, the value type must be (Display *). + + The created frame can be used for drawables whose root window is + the same as the root window for the default screen of the display, + and depth is the same as the default depth of the screen. + +
  • @b Mcolormap, the value type must be (Colormap). + + The created frame uses the specified colormap. + +
  • @b Mfont, the value must be #Mx, #Mfreetype, or #Mxft. + + The created frame uses the specified font backend. The value #Mx + instructs to use X core fonts, #Mfreetype to use local fonts + supported by FreeType fonts, and #Mxft to use local fonts via Xft + library. You can specify this parameter more than once with + different values if you want to use multiple font backends. This + is ignored if the specified font backend is not supported on the + device. + + When this parameter is not specified, all font backend supported + on the device are used. + +
+ + @return + If the operation was successful, mframe () returns a pointer to a + newly created frame. Otherwise, it returns @c NULL. */ + +/***ja + @brief �������ե졼�����. + + �ؿ� mframe () �� $PLIST ��Υѥ�᡼������Ŀ������ե졼����롣 + $PLIST �� @c NULL �Ǥ��ɤ��� + + $PLIST �˸����륭���Τ����ɤ줬ǧ������뤫�ϥ�����ɥ������ƥ�˰�¸���롣 + + �ʲ��Υ����Ͼ��ǧ������롣 + +
    + +
  • @b Mdevice. �ͤ� #Mx, @b Mgd, #Mnil �Τ����줫�Ǥʤ��ƤϤʤ�ʤ��� + + �ͤ� #Mx �ʤ�С��������ե졼��� X ������ɥ������ƥ��ѤǤ��롣 + ���Υե졼��ȶ��˻��ꤵ�줿���� #MDrawWindow �ϡ� @c Window + ���Ǥʤ��ƤϤʤ�ʤ����ե졼����ɤ߽񤭤Ȥ�˲�ǽ�Ǥ��ꡢ���٤Ƥ�GUI + �ؿ������ѤǤ��롣 + + �ͤ� @b Mgd �ʤ�С��������ե졼��� GD + �饤�֥��Υ��᡼�����֥��������ѤǤ��롣���Υե졼��ȶ��˻��ꤵ�줿���� + #MDrawWindow �ϡ� @c gdImagePtr ���Ǥʤ��ƤϤʤ�ʤ����ե졼��Ͻ񤭽Ф����ѤǤ��ꡢ + minput_ �ǻϤޤ�̾���δؿ��ϻ��ѤǤ��ʤ��� + + �ͤ� #Mnil �ʤ�С��������ե졼���, null + �ǥХ����ѤǤ��롣���Υե졼����ɤ߽񤭤Ǥ��ʤ��Τǡ����� #MDrawWindow + ��ɬ�פȤ���mdraw_ �ǻϤޤ�̾���δؿ��䡢minput_ �ǻϤޤ�̾���δؿ��ϻ��ѤǤ��ʤ��� + +
  • #Mface. �ͤ� #MFace �ؤΥݥ��󥿤Ǥʤ��ƤϤʤ�ʤ��� + + �����ͤϥե졼��Υǥե���ȤΥե������Ȥ����Ѥ����롣 + +
+ + �����Υ����˲ä���@b Mdevice �Υ����� #Mx + �Ǥ�����˸¤�ʲ��Υ�����ǧ������롣�ʲ��Υ����ϥ롼�ȥ�����ɥ��ȡ��ե졼������ѤǤ��� + drawable �ο�������ꤹ�롣 + +
    + +
  • @b Mdrawable. �ͤ� Drawable ���Ǥʤ��ƤϤʤ�ʤ��� + + ���� @b Mdisplay ����ĥѥ�᡼������ꤵ��Ƥ���ɬ�פ����롣 + �������줿�ե졼��ϡ����ꤵ�줿�ǥ����ץ쥤��λ��ꤵ�줿 drawable + ��Ʊ���롼�ȥ�����ɥ��ȿ�������� drawable ���Ѥ����롣 + + ���Υѥ�᡼����������ˤϡ�@b Mscreen �򥭡��Ȥ���ѥ�᡼����̵�뤵��롣 + +
  • @b Mwidget. �ͤ� Widget ���Ǥʤ��ƤϤʤ�ʤ��� + + �������줿�ե졼��ϡ����ꤷ�����������åȤ�Ʊ���롼�ȥ�����ɥ��ȿ�������� + drawable ���Ѥ����롣 + + ���� #Mface ����ĥѥ�᡼�����ʤ���С��ǥե���ȤΥե������Ϥ��� + ���������åȤΥ꥽�����������롣 + + ���Υѥ�᡼����������ˤϡ�@b Mdisplay, @b Mscreen, @b Mdrawable, + @b Mdepth �򥭡��Ȥ���ѥ�᡼����̵�뤵��롣 + +
  • @b Mdepth. �ͤ� unsigned ���Ǥʤ��ƤϤʤ�ʤ��� + + �������줿�ե졼��ϡ����ꤷ�������� drawable ���Ѥ����롣 + +
  • @b Mscreen. �ͤ� (Screen *) ���Ǥʤ��ƤϤʤ�ʤ��� + + ���������ե졼��ϡ����ꤷ�������꡼���Ʊ���롼�ȥ�����ɥ�������������꡼��Υǥե���Ȥο�����Ʊ����������� drawable ���Ѥ����롣 + + ���Υѥ�᡼����������ˤϡ�@b Mdisplay �򥭡��Ȥ���ѥ�᡼����̵�뤵��롣 + +
  • @b Mdisplay. �ͤ� (Display *) ���Ǥʤ��ƤϤʤ�ʤ��� + + �������줿�ե졼��ϡ����ꤷ���ǥ����ץ쥤�Υǥե���ȥ����꡼���Ʊ���롼�ȥ�����ɥ���Ʊ�����������drawables ���Ѥ����롣 + +
  • @b Mcolormap. �ͤ� (Colormap) ���Ǥʤ��ƤϤʤ�ʤ��� + + �������줿�ե졼��ϡ����ꤷ�����顼�ޥåפ���Ѥ��롣 + +
  • #Mfont. �ͤϡ�#Mx, #Mfreetype, #Mxft �Τ����줫�� + + �������줿�ե졼��ϻ��ꤷ���ե���ȥХå�����ɤ���Ѥ��롣�ͤ� + #Mx �Ǥ���� X �Υ����ե���ȡ�#Mfreetype �Ǥ���� FreeType + �ǥ��ݡ��Ȥ���Ƥ����������ե���ȡ�#Mxft �Ǥ���� Xft + �饤�֥���ͳ���Ѥ����������ե���Ȥ���Ѥ��롣 + ʣ���Υե���ȥХå�����ɤ���Ѥ��������ˤϡ����Υѥ�᡼����ʣ���󡢰ۤʤ��ͤǻ��ꤹ�뤳�Ȥ��Ǥ��롣 + ���ꤷ���Хå�����ɤ����ݡ��Ȥ���Ƥ��ʤ��ǥХ����Ǥϡ����Υѥ�᡼����̵�뤵��롣 + + ���Υѥ�᡼����̵�����ˤϡ��ǥХ����ǥ��ݡ��Ȥ���Ƥ��뤹�٤ƤΥե���ȥХå�����ɤ����Ѥ��롣 + +
+ + @return + ��������� mframe() �Ͽ������ե졼��ؤΥݥ��󥿤��֤��������Ǥʤ���� + @c NULL ���֤��� */ + +MFrame * +mframe (MPlist *plist) +{ + MFrame *frame; + int plist_created = 0; + MPlist *pl; + MSymbol device; + MDeviceLibraryInterface *interface; + + if (plist) + { + pl = mplist_find_by_key (plist, Mdevice); + if (pl) + device = MPLIST_VAL (pl); + else + device = Mx; + } + else + { + plist = mplist (); + plist_created = 1; + device = Mx; + } + + if (device == Mnil) + { +#ifdef HAVE_FREETYPE + interface = &null_interface; + if (! interface->handle) + { + (*interface->init) (); + interface->handle = (void *) 1; + } +#else /* not HAVE_FREETYPE */ + MERROR (MERROR_WIN, NULL); +#endif /* not HAVE_FREETYPE */ + } + else + { + interface = mplist_get (device_library_list, device); + if (! interface) + MERROR (MERROR_WIN, NULL); + if (! interface->handle) + { + if (! (interface->handle = dlopen (interface->library, RTLD_NOW)) + || ! (interface->init + = (int (*) ()) dlsym (interface->handle, "device_init")) + || ! (interface->open + = (int (*) (MFrame *, MPlist *)) dlsym (interface->handle, + "device_open")) + || ! (interface->fini + = (int (*) ()) dlsym (interface->handle, "device_fini")) + || (*interface->init) () < 0) + { + fprintf (stderr, "%s\n", (char *) dlerror ()); + if (interface->handle) + dlclose (interface->handle); + MERROR (MERROR_WIN, NULL); + } + } + } + + M17N_OBJECT (frame, free_frame, MERROR_FRAME); + if ((*interface->open) (frame, plist) < 0) + { + free (frame); + MERROR (MERROR_WIN, NULL); + } + + if (! mframe_default) + mframe_default = frame; + + frame->face = mface (); + MPLIST_DO (pl, plist) + if (MPLIST_KEY (pl) == Mface) + mface_merge (frame->face, (MFace *) MPLIST_VAL (pl)); + mface__update_frame_face (frame); + frame->font + = frame->rface->rfont ? (MFont *) frame->rface->rfont : NULL; + if (plist_created) + M17N_OBJECT_UNREF (plist); + return frame; +} + +/*=*/ + +/***en + @brief Return property value of frame. + + The mframe_get_prop () function returns a value of property $KEY + of frame $FRAME. The valid keys and the corresponding return + values are as follows. + +@verbatim + + key type of value meaning of value + --- ------------- ---------------- + Mface MFace * The default face. + + Mfont MFont * The default font. + + Mfont_width int Width of the default font. + + Mfont_ascent int Ascent of the default font. + + Mfont_descent int Descent of the default font. + +@endverbatim + + In the m17n-X library, the followings are also accepted. + +@verbatim + + key type of value meaning of value + --- ------------- ---------------- + Mdisplay Display * Display associated with the frame. + + Mscreen int Screen number of a screen associated + with the frame. + + Mcolormap Colormap Colormap of the frame. + + Mdepth unsigned Depth of the frame. +@endverbatim +*/ + +/***ja + @brief �ե졼��Υץ��ѥƥ����ͤ��֤�. + + �ؿ� mframe_get_prop () �ϥե졼�� $FRAME �Υ��� $KEY + ����ĥץ��ѥƥ����ͤ��֤���ͭ���ʥ����Ȥ����ͤϰʲ����̤ꡣ + +@verbatim + + ���� �ͤη� �ͤΰ�̣ + --- ------------- ---------------- + Mface MFace * �ǥե���ȤΥե����� + + Mfont MFont * �ǥե���ȤΥե���� + + Mfont_width int �ǥե���ȤΥե���Ȥ��� + + Mfont_ascent int �ǥե���ȤΥե���Ȥ� ascent + + Mfont_descent int �ǥե���ȤΥե���Ȥ� descent + +@endverbatim + + m17n-X �饤�֥��Ǥϡ��ʲ��Υ�������ѤǤ��롣 + +@verbatim + + ���� �ͤη� �ͤΰ�̣ + --- ------------- ---------------- + Mdisplay Display * �ե졼��ȴ�Ϣ�դ���줿�ǥ����ץ쥤 + + Mscreen int �ե졼��ȴ�Ϣ�դ���줿�����꡼�� + �Υ����꡼��ʥ�� + + Mcolormap Colormap �ե졼��Υ��顼�ޥå� + + Mdepth unsigned �ե졼��ο��� +@endverbatim + +*/ + +void * +mframe_get_prop (MFrame *frame, MSymbol key) +{ + if (key == Mface) + return frame->face; + if (key == Mfont) + return frame->font; + if (key == Mfont_width) + return (void *) (frame->average_width); + if (key == Mfont_ascent) + return (void *) (frame->ascent); + if (key == Mfont_descent) + return (void *) (frame->descent); + return (*frame->driver->get_prop) (frame, key); +} + +/*=*/ + +/***en + @brief The default frame. + + The external variable #mframe_default contains a pointer to the + default frame that is created by the first call of mframe (). */ + +/***ja + @brief �ǥե���ȤΥե졼��. + + �����ѿ� #mframe_default �ϡ��ǥե���ȤΥե졼��ؤΥݥ��󥿤���ġ� + �ǥե���ȤΥե졼��ϡ��ǽ�� mframe () ���ƤӽФ��줿�Ȥ��˺���롣 */ + +MFrame *mframe_default; + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/m17n-gui.h b/src/m17n-gui.h new file mode 100644 index 0000000..e5306ff --- /dev/null +++ b/src/m17n-gui.h @@ -0,0 +1,1061 @@ +/* m17n-gui.h -- header file for the GUI API of the m17n library. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_GUI_H_ +#define _M17N_GUI_H_ + +#ifndef _M17N_FLT_H_ +#include +#endif + +#ifndef _M17N_H_ +#include +#endif + +M17N_BEGIN_HEADER + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) + +extern void m17n_init_win (void); +#undef M17N_INIT +#define M17N_INIT() m17n_init_win () + +extern void m17n_fini_win (void); +#undef M17N_FINI +#define M17N_FINI() m17n_fini_win () + +#endif + +/***en @defgroup m17nGUI GUI API + @brief API provided by libm17n-gui.so */ +/***ja @defgroup m17nGUI GUI API + @brief libm17n-gui.so ���󶡤��� API */ +/*=*/ + +/*** @ingroup m17nGUI */ +/***en @defgroup m17nFrame Frame */ +/***ja @defgroup m17nFrame �ե졼�� */ +/*=*/ + +/*** @ingroup m17nFrame */ +/***en + @brief Type of frames. + + The type #MFrame is for a @e frame object. Each frame holds + various information about the corresponding physical display/input + device. + + The internal structure of the type #MFrame is concealed from an + application program, and its contents depend on the window system + in use. In the m17n-X library, it contains the information about + @e display and @e screen in the X Window System. */ + +/***ja + @brief �ե졼��η����. + + #MFrame �ϡ�@e �ե졼�� ���֥��������Ѥη��Ǥ��롣 + �ġ��Υե졼��ϡ����줬�б�����ʪ��Ū��ɽ�������ϥǥХ����γƼ������ݻ����롣 + + #MFrame ����������¤�ϡ����ץꥱ�������ץ�����फ��ϸ����ʤ��� + �ޤ��������Ƥϻ��Ѥ��륦����ɥ������ƥ�˰�¸���롣�ޤ� m17n-X + �饤�֥��ˤ�����ե졼��ϡ�X ������ɥ��� @e display �� @e screen + �˴ؤ���������ġ� */ + +typedef struct MFrame MFrame; + +/*=*/ + +extern MSymbol Mdevice; + +extern MSymbol Mfont; +extern MSymbol Mfont_width; +extern MSymbol Mfont_ascent; +extern MSymbol Mfont_descent; +extern MFrame *mframe_default; + +extern MSymbol Mdisplay; +extern MSymbol Mscreen; +extern MSymbol Mdrawable; +extern MSymbol Mwidget; +extern MSymbol Mdepth; +extern MSymbol Mcolormap; + +extern MFrame *mframe (MPlist *plist); + +extern void *mframe_get_prop (MFrame *frame, MSymbol key); + +/* end of frame module */ +/*=*/ + +/*** @ingroup m17nGUI */ +/***en @defgroup m17nFont Font */ +/***ja @defgroup m17nFont �ե���� */ +/*=*/ + +/*** @ingroup m17nFont */ +/***en + @brief Type of fonts. + + The type #MFont is the structure defining fonts. It contains + information about the following properties of a font: foundry, + family, weight, style, stretch, adstyle, registry, size, and + resolution. + + This structure is used both for specifying a font in a fontset + and for storing information about available system fonts. + + The internal structure is concealed from an application program. */ + +/***ja + @brief �ե���Ȥη����. + + #MFont ���ϥե���Ȼ����Ѥι�¤�ΤǤ��ꡢ�ե���ȤΥץ��ѥƥ��Ǥ��� + foundry, family, weight, style, stretch, adstyle, registry, + size, resolution �˴ؤ�������ޤࡣ + + ���ι�¤�Τϥե���ȥ��å���Υե���Ȥ���ꤹ��ݤȡ����Ѳ�ǽ�ʥ����ƥ�ե���Ȥξ�����Ǽ����ݤ�ξ�����Ѥ����롣 + + ������¤�ϥ��ץꥱ�������ץ�����फ��ϸ����ʤ��� */ + +/*** + @seealso + mfont (), mfont_from_name (), mfont_find (). */ + +typedef struct MFont MFont; + +/*=*/ + +extern MSymbol Mx, Mfreetype, Mxft; + +extern MPlist *mfont_freetype_path; + +extern MFont *mfont (); + +extern MFont *mfont_copy (MFont *font); + +extern MFont *mfont_parse_name (const char *name, MSymbol format); + +extern char *mfont_unparse_name (MFont *font, MSymbol format); + +/* These two are obsolete (from 1.1.0). */ +extern char *mfont_name (MFont *font); +extern MFont *mfont_from_name (const char *name); + +extern MSymbol Mfoundry; +extern MSymbol Mfamily; +extern MSymbol Mweight; +extern MSymbol Mstyle; +extern MSymbol Mstretch; +extern MSymbol Madstyle; +extern MSymbol Mspacing; +extern MSymbol Mregistry; +extern MSymbol Msize; +extern MSymbol Mresolution; +extern MSymbol Mmax_advance; +extern MSymbol Motf; +extern MSymbol Mfontfile; + +extern MSymbol Mfontconfig; + +extern void *mfont_get_prop (MFont *font, MSymbol key); + +extern int mfont_put_prop (MFont *font, MSymbol key, void *val); + +extern int mfont_set_encoding (MFont *font, + MSymbol encoding_name, MSymbol repertory_name); + + +/*=*/ + +/***en + @brief Find a font. + + The mfont_find () function returns a pointer to the available font + that matches best with the specification $SPEC in frame $FRAME. + + $SCORE, if not NULL, must point to a place to store the score + value which indicates how well the found font matches $SPEC. The + smaller score means a better match. + + $LIMITED_SIZE, if nonzero, forces the font selector to find a + font not greater than the #Msize property of $SPEC. */ + +/***ja + @brief �ե���Ȥ�õ��. + + �ؿ� mfont_find () �ϡ��ե졼�� $FRAME ��ǥե������� $SPEC + �ˤ�äȤ���פ�����Ѳ�ǽ�ʥե���ȤؤΥݥ��󥿤��֤��� + + $SCORE �� NULL �Ǥ��뤫�����Ĥ��ä��ե���Ȥ� $SPEC + �ˤɤ�ۤɹ�äƤ��뤫�򼨤�����������¸������ؤΥݥ��󥿤Ǥ��롣 + ���������������ۤ��ɤ���äƤ��뤳�Ȥ��̣���롣 + + $LIMITED_SIZE �� 0 �Ǥʤ���С�$SPEC �Υץ��ѥƥ� #Msize + ����礭���ʤ��ե���Ȥ�����õ����롣 +*/ + +extern MFont *mfont_find (MFrame *frame, MFont *spec, + int *score, int limited_size); +extern MSymbol *mfont_selection_priority (); + +extern int mfont_set_selection_priority (MSymbol *keys); + +extern int mfont_resize_ratio (MFont *font); + +extern MPlist *mfont_list (MFrame *frame, MFont *font, MSymbol language, + int maxnum); +extern MPlist *mfont_list_family_names (MFrame *frame); + +typedef struct MFontset MFontset; + +extern int mfont_check (MFrame *frame, MFontset *fontset, + MSymbol script, MSymbol language, MFont *font); + +extern int mfont_match_p (MFont *font, MFont *spec); + +extern MFont *mfont_open (MFrame *frame, MFont *font); + +extern MFont *mfont_encapsulate (MFrame *frame, MSymbol data_type, void *data); + +extern int mfont_close (MFont *font); + +/* end of font module */ +/*=*/ + +/*** @ingroup m17nGUI */ +/***en @defgroup m17nFontset Fontset */ +/***ja @defgroup m17nFontset �ե���ȥ��å� */ +/*=*/ +/*** @addtogroup m17nFontset + @{ */ +extern MFontset *mfontset (char *name); + +extern MSymbol mfontset_name (MFontset *fontset); + +extern MFontset *mfontset_copy (MFontset *fontset, char *name); + +extern int mfontset_modify_entry (MFontset *fontset, + MSymbol language, MSymbol script, + MSymbol charset, + MFont *spec, MSymbol layouter_name, + int how); + +extern MPlist *mfontset_lookup (MFontset *fontset, MSymbol script, + MSymbol language, MSymbol charset); +/*** @} */ +/* end of fontset module */ +/*=*/ + +/*** @ingroup m17nGUI */ +/***en @defgroup m17nFace Face */ +/***ja @defgroup m17nFace �ե����� */ +/*=*/ + +/*** @ingroup m17nFace */ +/***en + @brief Type of faces. + + The type #MFace is the structure of face objects. The internal + structure is concealed from an application program. */ + +/***ja + @brief �ե������η����. + + #MFace ���ϥե��������֥������ȤΤ���ι�¤�ΤǤ��롣 + ������¤�ϥ��ץꥱ�������ץ�����फ��ϸ����ʤ��� */ + +typedef struct MFace MFace; +/*=*/ + +extern MSymbol Mforeground; +extern MSymbol Mbackground; +extern MSymbol Mvideomode; +extern MSymbol Mnormal; +extern MSymbol Mreverse; +extern MSymbol Mhline; +extern MSymbol Mbox; +extern MSymbol Mfontset; +extern MSymbol Mratio; +extern MSymbol Mhook_func; +extern MSymbol Mhook_arg; + +/* Predefined faces. */ +extern MFace *mface_normal_video; +extern MFace *mface_reverse_video; +extern MFace *mface_underline; +extern MFace *mface_medium; +extern MFace *mface_bold; +extern MFace *mface_italic; +extern MFace *mface_bold_italic; +extern MFace *mface_xx_small; +extern MFace *mface_x_small; +extern MFace *mface_small; +extern MFace *mface_normalsize; +extern MFace *mface_large; +extern MFace *mface_x_large; +extern MFace *mface_xx_large; +extern MFace *mface_black; +extern MFace *mface_white; +extern MFace *mface_red; +extern MFace *mface_green; +extern MFace *mface_blue; +extern MFace *mface_cyan; +extern MFace *mface_yellow; +extern MFace *mface_magenta; + +/* etc */ +extern MSymbol Mface; + +extern MFace *mface (); + +extern int mface_equal (MFace *face1, MFace *face2); + +extern MFace *mface_copy (MFace *face); + +extern MFace *mface_merge (MFace *dst, MFace *src); + +extern MFace *mface_from_font (MFont *font); + +/*=*/ + +/*** @ingroup m17nFace */ +/***en + @brief Type of horizontal line spec of face. + + The type #MFaceHLineProp is to specify the detail of #Mhline + property of a face. The value of the property must be a pointer + to an object of this type. */ +/***ja + @brief �ե������ο�ʿ�������ѷ����. + + #MFaceHLineProp �ϥե������� #Mhline + �ץ��ѥƥ��ξܺ٤���ꤹ�뷿�Ǥ��롣���Υץ��ѥƥ����ͤϤ��η��Υ��֥������ȤǤʤ��ƤϤʤ�ʤ��� + */ + +typedef struct +{ + /***en Type of the horizontal line. */ + /***ja ��ʿ���Υ�����. */ + enum MFaceHLineType + { + MFACE_HLINE_BOTTOM, + MFACE_HLINE_UNDER, + MFACE_HLINE_STRIKE_THROUGH, + MFACE_HLINE_OVER, + MFACE_HLINE_TOP + } type; + + /***en Width of the line in pixels. */ + /***ja �����ʥԥ�����ñ�̡�. */ + unsigned width; + + /***en Color of the line. If the value is Mnil, foreground color of + a merged face is used. */ + /***ja ���ο�. Mnil �ʤ�С����礷���ե����������ʿ����Ȥ��롣 */ + + MSymbol color; +} MFaceHLineProp; +/*=*/ + +/*** @ingroup m17nFace */ +/***en + @brief Type of box spec of face. + + The type #MFaceBoxProp is to specify the detail of #Mbox property + of a face. The value of the property must be a pointer to an + object of this type. */ +/***ja + @brief �ե������ΰϤ��Ȼ����ѷ����. + + #MFaceBoxProp �ϥե������� #Mbox �ץ��ѥƥ��ξܺ٤���ꤹ�뷿�Ǥ��롣 + ���Υץ��ѥƥ����ͤϤ��η��Υ��֥������ȤؤΥݥ��󥿤Ǥʤ��ƤϤʤ�ʤ��� + */ + +typedef struct +{ + /***en Width of the box line in pixels. */ + /***ja �����ʥԥ�����ñ�̡�. */ + unsigned width; + + /* @{ */ + /*** Colors of borders. */ + MSymbol color_top; + MSymbol color_bottom; + MSymbol color_left; + MSymbol color_right; + /* @} */ + + /* @{ */ + /*** Margins */ + unsigned inner_hmargin; + unsigned inner_vmargin; + unsigned outer_hmargin; + unsigned outer_vmargin; + /* @} */ + +} MFaceBoxProp; +/*=*/ + +/*** @ingroup m17nFace */ +/***en + @brief Type of hook function of face. + + #MFaceHookFunc is a type of a hook function of a face. */ +/***ja + @brief �ե������Υեå��ؿ��η����. + + #MFaceHookFunc �ϥե������Υեå��ؿ��η��Ǥ��롣*/ +typedef void (*MFaceHookFunc) (MFace *face, void *arg, void *info); +/*=*/ + +extern void *mface_get_prop (MFace *face, MSymbol key); + +extern int mface_put_prop (MFace *face, MSymbol key, void *val); + +extern MFaceHookFunc mface_get_hook (MFace *face); + +extern int mface_put_hook (MFace *face, MFaceHookFunc func); + +extern void mface_update (MFrame *frame, MFace *face); + +/* end of face module */ +/*=*/ + +/*** @ingroup m17nGUI */ +/***en @defgroup m17nDraw Drawing */ +/***ja @defgroup m17nDraw ɽ�� */ +/*=*/ + +/*** @ingroup m17nDraw */ +/***en + @brief Window system dependent type for a window. + + The type #MDrawWindow is for a window; a rectangular area that + works in several ways like a miniature screen. + + What it actually points depends on a window system. A program + that uses the m17n-X library must coerce the type @c Drawable to + this type. */ +/***ja + @brief ������ɥ������ƥ�˰�¸���롢������ɥ��η����. + + #MDrawWindow �ϥ�����ɥ������ʤ�����Ĥ������ǥ����꡼��Υߥ˥��奢�Ȥ���Ư������ΰ��Ѥη��Ǥ��롣 + + �ºݤ˲���ؤ����ϥ�����ɥ������ƥ�˰�¸���롣 m17n X + �饤�֥������Ѥ���ץ������� @c Drawable ���򤳤η����Ѵ����ʤ��ƤϤʤ�ʤ��� */ + +typedef void *MDrawWindow; +/*=*/ + +/*** @ingroup m17nDraw */ +/***en + @brief Window system dependent type for a region. + + The type #MDrawRegion is for a region; an arbitrary set of pixels + on the screen (typically a rectangular area). + + What it actually points depends on a window system. A program + that uses the m17n-X library must coerce the type @c Region to + this type. */ +/***ja + @brief ������ɥ������ƥ�˰�¸���롢�ΰ�η����. + + #MDrawRegion ���ΰ衢���ʤ�������꡼����Ǥ�դΥԥ�����ν����ŵ��Ū�ˤ϶���ΰ���Ѥη��Ǥ��롣 + + �ºݤ˲���ؤ����ϥ�����ɥ������ƥ�˰�¸���롣 m17n X + �饤�֥������Ѥ���ץ������� @c Region ���򤳤η����Ѵ����ʤ��ƤϤʤ�ʤ��� */ + +typedef void *MDrawRegion; +/*=*/ + +/*** @ingroup m17nDraw */ +/***en + @brief Type of a text drawing control. + + The type #MDrawControl is the structure that controls how to draw + an M-text. */ +/***ja + @brief �ƥ�����ɽ������η����. + + #MDrawControl ���ϡ�M-text ��ɤ�ɽ�����뤫�����椹�빽¤�ΤǤ��롣 + */ + + +typedef struct +{ + /***en If nonzero, draw an M-text as image, i.e. with background + filled with background colors of faces put on the M-text. + Otherwise, the background is not changed. */ + /***ja 0 �Ǥʤ���С� M-text ������Ȥ��ơ����ʤ���طʤ� M-text + �Υե������ǻ��ꤵ��Ƥ����طʿ�������ɽ�����롣�����Ǥʤ�����طʤ��Ѥ��ʤ��� */ + unsigned as_image : 1; + + /***en If nonzero and the first glyph of each line has negative + lbearing, shift glyphs horizontally to right so that no pixel is + drawn to the left of the specified position. */ + /***ja 0 �Ǥʤ����ƹԤκǽ�Υ���դ� lbearing + ����ʤ�С�����դ��ʿ�˱��ˤ��餷�ơ����ꤷ�����֤�꺸�˥ԥ����뤬������ʤ��褦�ˤ��롣 */ + unsigned align_head : 1; + + /***en If nonzero, draw an M-text two-dimensionally, i.e., newlines + in M-text breaks lines and the following characters are drawn in + the next line. If \ is non-NULL, and the function + returns nonzero line width, a line longer than that width is + also broken. */ + /***ja 0 �Ǥʤ���С�M-text �򣲼���Ū�ˡ����ʤ�� M-text ��� + newline �Dz��Ԥ���³��ʸ���ϼ��ιԤ�ɽ�����롣�⤷ \ �� + NULL �Ǥʤ������δؿ��� 0 �Ǥʤ��������֤��С����������Ĺ���Ԥ���Ԥ���롣 */ + unsigned two_dimensional : 1; + + /***en If nonzero, draw an M-text to the right of a specified + position. */ + /***ja 0 �Ǥʤ���С�M-text ����ꤷ�����֤α���ɽ�����롣 */ + unsigned orientation_reversed : 1; + + /***en If nonzero, reorder glyphs correctly for bidi text. */ + /***ja 0 �ʤ���С�bidi �ƥ������Ѥ˥���դ����������󤹤롣 */ + unsigned enable_bidi : 1; + + /***en If nonzero, don't draw characters whose general category (in + Unicode) is Cf (Other, format). */ + /***ja 0 �Ǥʤ���С���˥����ɤ��֤�����̥��ƥ��꤬ Cf (Other, + format) �Ǥ���ʸ����ɽ�����ʤ��� */ + unsigned ignore_formatting_char : 1; + + /***en If nonzero, draw glyphs suitable for a terminal. Not yet + implemented. */ + /***ja 0 �Ǥʤ���С�ü���ѤΥ���դ�ɽ�����롣̤������ */ + unsigned fixed_width : 1; + + /***en If nonzero, draw glyphs with anti-aliasing if a backend font + driver supports it. */ + /***ja 0 �Ǥʤ���С�����������ꥢ���ǥ���դ�ɽ�����롣 + �ʥХå�����ɤΥե���ȥɥ饤�Ф�����������ꥢ����ǽ����ľ��Τߡ��� */ + unsigned anti_alias : 1; + + /***en If nonzero, disable the adjustment of glyph positions to + avoid horizontal overlapping at font boundary. */ + /***ja 0 �Ǥʤ���С��ե���ȶ����Ǥο�ʿ�����Υ���դνŤʤ���򤱤뤿��Υ���հ��֤�Ĵ����̵���ˤ��롣 */ + unsigned disable_overlapping_adjustment : 1; + + /***en If nonzero, the values are minimum line ascent pixels. */ + /***ja 0 �Ǥʤ���С��ͤϹԤ� ascent �κǾ��ͤ򼨤��� */ + unsigned int min_line_ascent; + /***en If nonzero, the values are minimum line descent pixels. */ + /***ja 0 �Ǥʤ���С��ͤϹԤ� descent �κǾ��ͤ򼨤��� */ + unsigned int min_line_descent; + + /***en If nonzero, the values are maximum line ascent pixels. */ + /***ja 0 �Ǥʤ���С��ͤϹԤ� ascent �κ����ͤ򼨤��� */ + unsigned int max_line_ascent; + /***en If nonzero, the values are maximum line descent pixels. */ + /***ja 0 �Ǥʤ���С��ͤϹԤ� descent �κ����ͤ򼨤��� */ + unsigned int max_line_descent; + + /***en If nonzero, the value specifies how many pixels each line can + occupy on the display. The value zero means that there is no + limit. It is ignored if \ is non-NULL. */ + /***ja 0 �Ǥʤ���С��ͤϤ��Υǥ����ץ쥤��dzƹԤ����뤳�ȤΤǤ���ԥ�������򼨤��� + 0 �ϸ��ꤵ��ʤ����Ȥ��̣���롣\ �� NULL �Ǥʤ����̵�뤵��롣 */ + unsigned int max_line_width; + + /***en If nonzero, the value specifies the distance between tab + stops in columns (the width of one column is the width of a + space in the default font of the frame). The value zero means + 8. */ + /***ja 0 �Ǥʤ���С��ͤϥ��֥��ȥå״֤ε�Υ�򥳥��ñ�� + �ʥ����ϥե졼��Υǥե���ȥե���Ȥˤ��������ʸ�������Ǥ���ˤǼ����� + 0 �� 8 ���̣���롣 */ + unsigned int tab_width; + + /***en If non-NULL, the value is a function that calculates the + indentation and width limit of each line based on the line + number LINE and the coordinate Y. The function store the + indentation and width limit at the place pointed by INDENT and + WIDTH respectively. + + The indentation specifies how many pixels the first glyph of + each line is shifted to the right (if the member + \ is zero) or to the left (otherwise). If + the value is negative, each line is shifted to the reverse + direction. + + The width limit specifies how many pixels each line can occupy + on the display. The value 0 means that there is no limit. + + LINE and Y are reset to 0 when a line is broken by a newline + character, and incremented each time when a long line is broken + because of the width limit. + + This has an effect only when \ is nonzero. */ + /***ja 0 �Ǥʤ���С��ͤϴؿ��Ǥ��ꡢ���δؿ��Ϲ��ֹ� LINE �Ⱥ�ɸ Y + �˴�Ť��ƳƹԤΥ���ǥ�ȤȺ�������׻��������줾���INDENT �� + WIDTH �ǻؤ���������¸���롣 + + ����ǥ�Ȥϡ��ƹԤκǽ�Υ���դ򱦡ʥ��� + \ �� 0 + �λ��ˤ��뤤�Ϻ��ʤ���ʳ��λ��ˤ˲��ԥ����뤺�餹������ꤹ�롣�ͤ���ʤ�е������ˤ��餹�� + + �������ϡ��ƹԤ��ǥ����ץ쥤������뤳�ȤΤǤ���ԥ�������κ����ͤǤ��롣�ͤ� + 0 �ξ������¤�����ʤ����Ȥ��̣���롣 + + LINE �� Y �ϲ���ʸ���ˤ�äƹԤ����ޤä��ݤˤ� 0 + �˥ꥻ�åȤ��졢Ĺ���Ԥ������������¤ˤ�äƲ��Ԥ���뤿�Ӥ� 1 ���䤵��롣 + + ����� \ �� 0 �Ǥʤ����ˤΤ�ͭ���Ǥ��롣 */ + void (*format) (int line, int y, int *indent, int *width); + + /***en If non-NULL, the value is a function that calculates a line + breaking position when a line is too long to fit within the + width limit. POS is the position of the character next to the + last one that fits within the limit. FROM is the position of the + first character of the line, and TO is the position of the last + character displayed on the line if there were not width limit. + LINE and Y are the same as the arguments to \. + + The function must return a character position to break the + line. + + The function should not modify MT. + + The mdraw_default_line_break () function is useful for such a + script that uses SPACE as a word separator. */ + /***ja NULL �Ǥʤ���С��ͤϹԤ���������˼��ޤ�ʤ����˹Ԥ�������֤�׻�����ؿ��Ǥ��롣 + POS �Ϻ������˼��ޤ�Ǹ��ʸ���μ���ʸ���ΰ��֤Ǥ��롣FROM + �ϹԤκǽ��ʸ���ΰ��֡�TO + �Ϻ����������ꤵ��Ƥ��ʤ���Ф��ιԤ�ɽ�������Ǹ��ʸ���ΰ��֤Ǥ��롣LINE + �� Y �� \ �ΰ�����Ʊ�ͤǤ��롣 + + ���δؿ��ϹԤ�����ʸ�����֤��֤��ʤ��ƤϤʤ�ʤ����ޤ� MT ���ѹ����ƤϤʤ�ʤ��� + + �ؿ� mdraw_default_line_break () + �ϡ�������ζ��ڤ�Ȥ����Ѥ��륹����ץ��ѤȤ���ͭ�ѤǤ��롣 */ + int (*line_break) (MText *mt, int pos, int from, int to, int line, int y); + + /***en If nonzero, show the cursor according to \. */ + /***ja �����Ǥʤ���� \ �ˤ������äƥ��������ɽ�����롣 */ + int with_cursor; + + /***en Specifies the character position to display a cursor. If it + is greater than the maximum character position, the cursor is + displayed next to the last character of an M-text. If the value + is negative, even if \ is nonzero, cursor is not + displayed. */ + /***ja ���������ɽ������ʸ�����֤򼨤��������ʸ�����֤���礭����С���������� + M-text �κǸ��ʸ�����٤�ɽ������롣��ʤ�С� + \ �� 0 �Ǥʤ��Ƥ⥫�������ɽ������ʤ��� + */ + int cursor_pos; + + /***en If nonzero, display a cursor at the character position + \. If the value is positive, it is the pixel width + of the cursor. If the value is negative, the cursor width is + the same as the underlining glyph(s). */ + /***ja 0 �Ǥʤ���С�\ �˥��������ɽ�����롣 + �ͤ����ʤ�С�������������Ϥ����͡ʥԥ�����ñ�̡ˤǤ��롣 + ��ʤ�С���������Τ��륰��դ�Ʊ�����Ǥ��롣 */ + int cursor_width; + + /***en If nonzero and \ is also nonzero, display double + bar cursors; at the character position \ and at the + logically previous character. Both cursors have one pixel width + with horizontal fringes at upper or lower positions. */ + /***ja If 0 �Ǥʤ������� \ �� 0 �Ǥʤ���С��С����������ʸ������ + \ ������Ū�ˤ�������ˤ���ʸ���Σ������ɽ�����롣 + �����Ȥ⣱�ԥ��������ǡ��夫���˿�ʿ�ξ��꤬�Ĥ���*/ + int cursor_bidi; + + /***en If nonzero, on drawing partial text, pixels of surrounding + texts that intrude into the drawing area are also drawn. For + instance, some CVC sequence of Thai text (C is consonant, V is + upper vowel) is drawn so that V is placed over the middle of two + Cs. If this CVC sequence is already drawn and only the last C + is drawn again (for instance by updating cursor position), the + right half of V is erased if this member is zero. By setting + this member to nonzero, even with such a drawing, we can keep + this CVC sequence correctly displayed. */ + /***ja 0 �Ǥʤ���С��ƥ����Ȥΰ���ʬ��ɽ������ݤˡ�����Υƥ����ȤΤ�������ɽ���ΰ�˿���������ʬ��ɽ�����롣 + ���Ȥ��С�������ƥ����� �Ҳ�-�첻-�Ҳ� + �Ȥ������������󥹤Τ����Ĥ��ϡ��첻����ĤλҲ��δ֤˾�ˤΤ�褦��������롣 + ���Τ褦�ʥ��������󥹤����Ǥ�������Ƥ��ꡢ�Ǹ�λҲ�����������ľ����� + �ʤ��Ȥ��С�����������֤򹹿�����ݤʤɡˤ��Υ��Ф� 0 + �Ǥ���С��첻�α�Ⱦʬ���ä���Ƥ��ޤ�������� 0 �ʳ��ˤ��뤳�Ȥˤ�äơ����Τ褦�ʺݤˤ� + �Ҳ�-�첻-�Ҳ� �Υ��������󥹤�������ɽ����³���뤳�Ȥ��Ǥ��롣 */ + int partial_update; + + /***en If nonzero, don't cache the result of any drawing information + of an M-text. */ + /***ja 0 �Ǥʤ���С�M-text ��ɽ���˴ؤ������򥭥�å��夷�ʤ��� + */ + int disable_caching; + + /***en If non-NULL, limit the drawing effect to the specified region. */ + /***ja NULL �Ǥʤ����ɽ�����ꥢ����ꤵ�줿�ΰ�˸��ꤹ�롣 */ + MDrawRegion clip_region; + +} MDrawControl; + +extern int mdraw_line_break_option; + +/*=*/ + +/*** @ingroup m17nDraw */ +/***en + @brief Type of metric for glyphs and texts. + + The type #MDrawMetric is for a metric of a glyph and a drawn text. + It is also used to represent a rectangle area of a graphic + device. */ +/***ja + @brief ����դȥƥ����Ȥ���ˡ�η����. + + #MDrawMetric �ϥ���դ�ɽ�����줿�ƥ����Ȥ���ˡ�Ѥη��Ǥ��롣 + �ޤ���ɽ���ǥХ����ζ���ΰ��ɽ���Τˤ��Ѥ����롣 */ + +typedef struct { + /*** X coordinates of a glyph or a text. */ + int x; + /*** Y coordinates of a glyph or a text. */ + int y; + /*** Pixel width of a glyph or a text. */ + unsigned int width; + /*** Pixel height of a glyph or a text. */ + unsigned int height; +} MDrawMetric; + +/*=*/ + +/*** @ingroup m17nDraw */ +/***en + @brief Type of information about a glyph. + + The type #MDrawGlyphInfo is the structure that contains + information about a glyph. It is used by mdraw_glyph_info (). */ +/***ja + @brief ����դ˴ؤ������η����. + + #MDrawGlyphInfo ���ϥ���դ˴ؤ�������ޤ๽¤�ΤǤ��롣 + mdraw_glyph_info () �Ϥ�����Ѥ��롣 */ + +typedef struct +{ + /***en Start position of character range corresponding to the glyph. */ + /***ja ����դ��б�����ʸ�����ϰϤγ��ϰ���. */ + int from; + + /***en End position of character range corresponding to the glyph. */ + /***ja ����դ��б�����ʸ�����ϰϤν�λ����. */ + int to; + + /***en Start position of character range corresponding to the line of the glyph. */ + /***ja ��ԤΥ���դ�����б�����ʸ�����ϰϤγ��ϰ���. */ + int line_from; + /***en End position of character range corresponding to the line of the glyph. */ + /***ja ��ԤΥ���դ�����б�����ʸ�����ϰϤν�λ����. */ + int line_to; + + /***en X coordinates of the glyph. */ + /***ja ����դ� X ��ɸ. */ + int x; + /***en Y coordinates of the glyph. */ + /***ja ����դ� Y ��ɸ. */ + int y; + + /***en Metric of the glyph. */ + /***ja ����դ���ˡ. */ + MDrawMetric metrics; + + /***en Font used for the glyph. Set to NULL if no font is found for + the glyph. */ + /***ja ����դ˻Ȥ���ե���ȡ����Ĥ���ʤ���� NULL�� */ + + MFont *font; + + /***en Character ranges corresponding to logically previous glyphs. + Note that we do not need the members prev_to because it must + be the same as the member \. */ + /***ja ����Ū�����Υ���դ��б�����ʸ�����ϰϡ����� prev_to �ϡ��� + ��� from ��Ʊ���Ǥ���Ϥ��ʤΤ����פǤ��롣 */ + int prev_from; + /***en Character ranges corresponding to logically next glyphs. + Note that we do not need the members next_from because it must + be the same as the member \ respectively. */ + /***ja ����Ū�ʸ�Υ���դ��б�����ʸ�����ϰϡ����� next_from �� + ���� to ��Ʊ���Ǥ���Ϥ��ʤΤ����פǤ��롣 */ + int next_to; + + /***en Start position of character ranges corresponding to visually + left glyphs. */ + /***ja ɽ����κ��Υ���դ��б�����ʸ�����ϰϤγ��ϰ��֡� */ + int left_from; + /***en End position of character ranges corresponding to visually + left glyphs. */ + /***ja ɽ����κ��Υ���դ��б�����ʸ�����ϰϤν�λ���֡� */ + int left_to; + /***en Start position of character ranges corresponding to visually + right glyphs. */ + /***ja ɽ����α��Υ���դ��б�����ʸ�����ϰϤγ��ϰ��֡� */ + int right_from; + /***en End position of character ranges corresponding to visually + left glyphs. */ + /***ja ɽ����α��Υ���դ��б�����ʸ�����ϰϤν�λ���֡� */ + int right_to; + + /***en Logical width of the glyph. Nominal distance to the next + glyph. */ + /***ja ����դ�����Ū�������Υ���դȤ�̾�ܾ�ε�Υ�� */ + int logical_width; +} MDrawGlyphInfo; + +/*=*/ + +/*** @ingroup m17nDraw */ +/***en + @brief Type of information about a glyph metric and font. + + The type #MDrawGlyph is the structure that contains information + about a glyph metric and font. It is used by the function + mdraw_glyph_list (). */ +/***ja + @brief ����դ���ˡ�ȥե���Ȥ˴ؤ������η����. + + #MDrawGlyph ���ϥ���դ���ˡ�ȥե���Ȥ˴ؤ�������ޤ๽¤�ΤǤ��롣 + mdraw_glyph_list () �Ϥ�����Ѥ��롣 */ + +typedef struct +{ + /* @{ */ + /***en Character range corresponding to the glyph. */ + /***ja ����դ��б�����ʸ�����ϰ�. */ + int from, to; + /* @} */ + + /***en Font glyph code of the glyph. */ + /***ja �ե������Υ���ե����ɡ� */ + int glyph_code; + + /***en Logical width of the glyph. Nominal distance to the next + glyph. */ + /***ja ����դ�����Ū�������Υ���դȤ�̾�ܾ�ε�Υ�� */ + int x_advance; + /***en Logical height of the glyph. Nominal distance to the next + glyph. */ + /***ja ����դ�����Ū�⤵�����Υ���դȤ�̾�ܾ�ε�Υ�� */ + int y_advance; + + /***en X offset relative to the glyph position. */ + /***ja ����դΰ��֤��Ф��� X ���ե��å�. */ + int x_off; + /***en Y offset relative to the glyph position. */ + /***ja ����դΰ��֤��Ф��� Y ���ե��å�. */ + int y_off; + + /***en Metric of the glyph (left-bearing). */ + /***ja ����դ���ˡ (left-bearing). */ + int lbearing; + /***en Metric of the glyph (right-bearing). */ + /***ja ����դ���ˡ (right-bearing). */ + int rbearing; + /***en Metric of the glyph (ascent). */ + /***ja ����դ���ˡ (ascent). */ + int ascent; + /***en Metric of the glyph (descent). */ + /***ja ����դ���ˡ (descent). */ + int descent; + + /***en Font used for the glyph. Set to NULL if no font is found for + the glyph. */ + /***ja ����դ˻Ȥ���ե���ȡ����Ĥ���ʤ���� NULL�� */ + MFont *font; + + /***en Type of the font. One of Mx, Mfreetype, Mxft. */ + /***ja �ե���ȤΥ����ס�Mx��Mfreetype��Mxft �Τ����줫�� */ + MSymbol font_type; + + /***en Pointer to the font structure. The actual type is + (XFontStruct *) if \ member is Mx, FT_Face if + \ member is Mfreetype, and (XftFont *) if \ + member is Mxft. */ + /***ja �ե���Ȥι�¤�ΤؤΥݥ��󥿡��ºݤη��� \ ���Ф� + Mx �ʤ� (XFontStruct *)�� Mfreetype �ʤ� FT_Face��Mxft + �ʤ� (XftFont *)�� */ + void *fontp; + +} MDrawGlyph; + +/*=*/ + +/***en + @brief Type of textitems. + + The type #MDrawTextItem is for @e textitem objects. + Each textitem contains an M-text and some other information to + control the drawing of the M-text. */ + +/***ja + @brief textitem �η����. + + #MDrawTextItem �� @e �ƥ����ȥ����ƥ� ���֥��������Ѥη��Ǥ��롣 + �ƥƥ����ȥ����ƥ�ϡ� 1 �Ĥ� M-text �ȡ�����ɽ�������椹�뤿��ξ����ޤ�Ǥ��롣 + + @latexonly \IPAlabel{MTextItem} @endlatexonly */ + +typedef struct +{ + /***en M-text. */ + /***ja M-text. */ + MText *mt; + + /***en Optional change in the position (in the unit of pixel) along + the X-axis before the M-text is drawn. */ + /***ja M-text ɽ�����˹Ԥʤ�X�������ΰ���Ĵ�� (�ԥ�����ñ��) */ + int delta; + + /***en Pointer to a face object. Each property of the face, if not + Mnil, overrides the same property of face(s) specified as a text + property in \. */ + /***ja �ե��������֥������ȤؤΥݥ��󥿡��ե������γƥץ��ѥƥ��� + Mnil �Ǥʤ���� \ �ǻ��ꤵ�줿�ե�������Ʊ���ץ��ѥƥ���ͥ�褹��*/ + MFace *face; + + /***en Pointer to a draw control object. The M-text \ is drawn + by mdraw_text_with_control () with this control object. */ + /***ja ɽ�����楪�֥������ȤؤΥݥ��󥿡� mdraw_text_with_control () + �Ϥ��Υ��֥������Ȥ��Ѥ��� M-text \ ��ɽ�����롣 */ + MDrawControl *control; + +} MDrawTextItem; + +/*=*/ + +extern int mdraw_text (MFrame *frame, MDrawWindow win, int x, int y, + MText *mt, int from, int to); + +extern int mdraw_image_text (MFrame *frame, MDrawWindow win, int x, int y, + MText *mt, int from, int to); + +extern int mdraw_text_with_control (MFrame *frame, MDrawWindow win, + int x, int y, MText *mt, int from, int to, + MDrawControl *control); + +extern int mdraw_coordinates_position (MFrame *frame, + MText *mt, int from, int to, + int x, int y, MDrawControl *control); + +extern int mdraw_text_extents (MFrame *frame, + MText *mt, int from, int to, + MDrawControl *control, + MDrawMetric *overall_ink_return, + MDrawMetric *overall_logical_return, + MDrawMetric *overall_line_return); + +extern int mdraw_text_per_char_extents (MFrame *frame, + MText *mt, int from, int to, + MDrawControl *control, + MDrawMetric *ink_array_return, + MDrawMetric *logical_array_return, + int array_size, + int *num_chars_return, + MDrawMetric *overall_ink_return, + MDrawMetric *overall_logical_return); + +extern int mdraw_glyph_info (MFrame *frame, MText *mt, int from, int pos, + MDrawControl *control, MDrawGlyphInfo *info); + +extern int mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to, + MDrawControl *control, MDrawGlyph *glyphs, + int array_size, int *num_glyphs_return); + +extern void mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y, + MDrawTextItem *items, int nitems); + +extern void mdraw_per_char_extents (MFrame *frame, MText *mt, + MDrawMetric *array_return, + MDrawMetric *overall_return); + +extern int mdraw_default_line_break (MText *mt, int pos, + int from, int to, int line, int y); + +extern void mdraw_clear_cache (MText *mt); + +/* end of drawing module */ +/*=*/ + +/*** @ingroup m17nGUI */ +/***en @defgroup m17nInputMethodWin Input Method (GUI) */ +/***ja @defgroup m17nInputMethodWin ���ϥ᥽�å� (GUI) */ +/*=*/ + +extern MInputDriver minput_gui_driver; + +/*=*/ +/*** @ingroup m17nInputMethodWin */ +/***en + @brief Type of the argument to the function minput_create_ic (). + + The type #MInputGUIArgIC is for the argument $ARG of the function + minput_create_ic () to create an input context of an internal + input method. */ + +/***ja + @brief �ؿ� minput_create_ic () �ΰ����η����. + + #MInputGUIArgIC �ϡ��ؿ� minput_create_ic () + ���������ϥ᥽�åɤ����ϥ���ƥ����Ȥ���������ݤΡ����� $ARG �Ѥη��Ǥ��롣 */ + +typedef struct +{ + /***en Frame of the client. */ + /***ja ���饤����ȤΥե졼�� */ + MFrame *frame; + + /***en Window on which to display the preedit and status text. */ + /***ja preedit �ƥ����Ȥ� status �ƥ����Ȥ�ɽ�����륦����ɥ� */ + MDrawWindow client; + + /***en Window that the input context has a focus on. */ + /***ja ���ϥ���ƥ����Ȥ��ե��������򤪤��Ƥ��륦����ɥ� */ + MDrawWindow focus; +} MInputGUIArgIC; + +/*=*/ + +extern MSymbol minput_event_to_key (MFrame *frame, void *event); + +/* end of input module */ +/*=*/ +/* end of window modules */ +/*=*/ + +extern MFace *mdebug_dump_face (MFace *face, int indent); +extern MFont *mdebug_dump_font (MFont *font); +extern MFontset *mdebug_dump_fontset (MFontset *fontset, int indent); + +M17N_END_HEADER + +#endif /* _M17N_GUI_H_ */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/m17n-misc.h b/src/m17n-misc.h new file mode 100644 index 0000000..d3976f5 --- /dev/null +++ b/src/m17n-misc.h @@ -0,0 +1,134 @@ +/* m17n-misc.h -- header file for the MISC API. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_ERR_H_ +#define _M17N_ERR_H_ + +#ifndef _M17N_CORE_H_ +#include +#endif + +M17N_BEGIN_HEADER + +/*** @defgroup m17nMisc MISC API */ +/***en @brief Miscellaneous API */ +/***ja @brief ����¾�� API */ +/*=*/ +/*** @ingroup m17nMisc */ +/***en @defgroup m17nError Error Handling */ +/***ja @defgroup m17nError ���顼���� */ +/*=*/ + +/*** @ingroup m17nError */ +/***en + @brief Enumeration for error code of the m17n library. + + Enumeration for error code of the m17n library. + + When a library function is called with an invalid argument, it + sets the external variable #merror_code to one of these values. + All the error codes are positive integers. + + When a memory allocation error happens, the function pointed to by + the external variable #m17n_memory_full_handler is called with one + of these values as an argument. */ + +/***ja + @brief m17n �饤�֥�ꥨ�顼�����ɤ����. + + m17n �饤�֥�ꥨ�顼�����ɤ���� + + �饤�֥��δؿ��������Ǥʤ������ȤȤ�˸ƤФ줿���ˤϡ��ѿ� + #merror_code �򤳤����ͤΤɤ줫�˥��åȤ��롣���٤ƤΥ��顼�����ɤ����������Ǥ��롣 + + ��������ƥ��顼�κݤˤϡ������ѿ� #m17n_memory_full_handler + �λؤ��ؿ������������ͤΤ����Τɤ줫������Ȥ��ƸƤФ�롣 + */ + +enum MErrorCode + { + MERROR_NONE, + MERROR_OBJECT, + MERROR_SYMBOL, + MERROR_MTEXT, + MERROR_TEXTPROP, + MERROR_CHAR, + MERROR_CHARTABLE, + MERROR_CHARSET, + MERROR_CODING, + MERROR_RANGE, + MERROR_LANGUAGE, + MERROR_LOCALE, + MERROR_PLIST, + MERROR_MISC, + MERROR_WIN, + MERROR_X, + MERROR_FRAME, + MERROR_FACE, + MERROR_DRAW, + MERROR_FLT, + MERROR_FONT, + MERROR_FONTSET, + MERROR_FONT_OTF, + MERROR_FONT_X, + MERROR_FONT_FT, + MERROR_IM, + MERROR_DB, + MERROR_IO, + MERROR_DEBUG, + MERROR_MEMORY, + MERROR_GD, + MERROR_MAX + }; + +/*=*/ + +extern void (*m17n_memory_full_handler) (enum MErrorCode err); + +/*=*/ +/*** @ingroup m17nMisc */ +/***en @defgroup m17nDebug Debugging */ +/***ja @defgroup m17nDebug �ǥХå����ݡ��� */ +/*=*/ + +extern int mdebug_hook (void); + +extern MSymbol mdebug_dump_symbol (MSymbol sym, int indent); +extern MSymbol mdebug_dump_all_symbols (int indent); +extern MPlist *mdebug_dump_plist (MPlist *plist, int indent); +extern MText *mdebug_dump_mtext (MText *mt, int fullp, int indent); +extern MCharTable *mdebug_dump_chartab (MCharTable *table, int indent); + +#ifdef DOXYGEN_INTERNAL_MODULE +/***en @defgroup m17nInternal Internal */ +/***ja @defgroup m17nInternal Internal */ +#endif + +M17N_END_HEADER + +#endif /* _M17N_ERR_H_ */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/m17n.c b/src/m17n.c new file mode 100644 index 0000000..5e9431d --- /dev/null +++ b/src/m17n.c @@ -0,0 +1,129 @@ +/* m17n.c -- body of the SHELL API. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#include +#include + +#include "m17n.h" +#include "m17n-misc.h" +#include "internal.h" +#include "charset.h" +#include "coding.h" + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) + + +/* Internal API */ + + +/* External API */ + +void +m17n_init (void) +{ + int mdebug_flag = MDEBUG_INIT; + + merror_code = MERROR_NONE; + if (m17n__shell_initialized++) + return; + m17n_init_core (); + if (merror_code != MERROR_NONE) + { + m17n__shell_initialized--; + return; + } + MDEBUG_PUSH_TIME (); + MDEBUG_PUSH_TIME (); + if (mcharset__init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", + (mdebug__output, " to initialize charset module.")); + if (mcoding__init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize conv module.")); + if (mcharset__load_from_database () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to load charset definitions.")); + if (mcoding__load_from_database () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to load coding definitions.")); + if (mlang__init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", + (mdebug__output, " to initialize language module")); + if (mlocale__init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize locale module.")); + if (minput__init () < 0) + goto err; + MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize input module.")); + + err: + MDEBUG_POP_TIME (); + MDEBUG_PRINT_TIME ("INIT", + (mdebug__output, " to initialize the shell modules.")); + MDEBUG_POP_TIME (); +} + +void +m17n_fini (void) +{ + int mdebug_flag = MDEBUG_FINI; + + if (m17n__shell_initialized == 0 + || --m17n__shell_initialized > 0) + return; + + MDEBUG_PUSH_TIME (); + MDEBUG_PUSH_TIME (); + minput__fini (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize input module.")); + mlocale__fini (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize locale module.")); + mlang__fini (); + MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize language module.")); + mchar__fini (); + MDEBUG_PRINT_TIME ("FINI", + (mdebug__output, " to finalize character module.")); + mdatabase__fini (); + MDEBUG_PRINT_TIME ("FINI", + (mdebug__output, " to finalize database module.")); + mcoding__fini (); + MDEBUG_PRINT_TIME ("FINI", + (mdebug__output, " to finalize coding module.")); + mcharset__fini (); + MDEBUG_PRINT_TIME ("FINI", + (mdebug__output, " to finalize charset module.")); + MDEBUG_POP_TIME (); + MDEBUG_PRINT_TIME ("FINI", + (mdebug__output, " to finalize the shell modules.")); + MDEBUG_POP_TIME (); + m17n_fini_core (); +} + +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/m17n.h b/src/m17n.h new file mode 100644 index 0000000..5528d8e --- /dev/null +++ b/src/m17n.h @@ -0,0 +1,1406 @@ +/* m17n.h -- header file for the SHELL API of the m17n library. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_H_ +#define _M17N_H_ + +#include +#include +#include + +#ifndef _M17N_CORE_H_ +#include +#endif + +M17N_BEGIN_HEADER + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +extern void m17n_init (void); +#undef M17N_INIT +#ifdef _M17N_FLT_H_ +#define M17N_INIT() \ + do { \ + m17n_init (); \ + m17n_init_flt (); \ + } while (0) +#else /* not _M17N_FLT_H_ */ +#define M17N_INIT() m17n_init () +#endif /* not _M17N_FLT_H_ */ + +extern void m17n_fini (void); +#undef M17N_FINI +#ifdef _M17N_FLT_H_ +#define M17N_FINI() \ + do { \ + m17n_fini_flt (); \ + m17n_fini (); \ + } while (0) +#else /* not _M17N_FLT_H_ */ +#define M17N_FINI() m17n_fini () +#endif /* not _M17N_FLT_H_ */ + +#endif + +/***en @defgroup m17nShell SHELL API + @brief API provided by libm17n.so */ +/***ja @defgroup m17nShell ������ API + @brief libm17n.so ���󶡤��� API */ +/*=*/ + +/* + * (11) Functions related to the m17n database + */ +/*=*/ + +/*=*/ +/* (S2) Charset staffs */ +/*=*/ + +/*** @ingroup m17nShell */ +/***en @defgroup m17nCharset Charset */ +/***ja @defgroup m17nCharset ʸ�����å� */ +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +#define MCHAR_INVALID_CODE 0xFFFFFFFF +#endif + +/* Predefined charsets */ +extern MSymbol Mcharset_ascii; +extern MSymbol Mcharset_iso_8859_1; +extern MSymbol Mcharset_unicode; +extern MSymbol Mcharset_m17n; +extern MSymbol Mcharset_binary; + +/* Predefined keys for mchar_define_charset (). */ +extern MSymbol Mmethod; +extern MSymbol Mdimension; +extern MSymbol Mmin_range; +extern MSymbol Mmax_range; +extern MSymbol Mmin_code; +extern MSymbol Mmax_code; +extern MSymbol Mascii_compatible; +extern MSymbol Mfinal_byte; +extern MSymbol Mrevision; +extern MSymbol Mmin_char; +extern MSymbol Mmapfile; +extern MSymbol Mparents; +extern MSymbol Msubset_offset; +extern MSymbol Mdefine_coding; +extern MSymbol Maliases; + +/* Methods of a charset. */ +extern MSymbol Moffset; +extern MSymbol Mmap; +extern MSymbol Munify; +extern MSymbol Msubset; +extern MSymbol Msuperset; + +/* etc. */ +extern MSymbol mchar_define_charset (const char *name, MPlist *plist); + +extern MSymbol mchar_resolve_charset (MSymbol symbol); + +extern int mchar_list_charset (MSymbol **symbols); + +extern int mchar_decode (MSymbol charset_name, unsigned code); + +extern unsigned mchar_encode (MSymbol charset_name, int c); + +extern int mchar_map_charset (MSymbol charset_name, + void (*func) (int from, int to, void *arg), + void *func_arg); + +/*=*/ + +/* (S3) code conversion */ +/*=*/ +/*** @ingroup m17nShell */ +/***en @defgroup m17nConv Code Conversion */ +/***ja @defgroup m17nConv �������Ѵ� */ +/*=*/ + +/* Predefined coding systems */ +extern MSymbol Mcoding_us_ascii; +extern MSymbol Mcoding_iso_8859_1; +extern MSymbol Mcoding_utf_8; +extern MSymbol Mcoding_utf_8_full; +extern MSymbol Mcoding_utf_16; +extern MSymbol Mcoding_utf_16be; +extern MSymbol Mcoding_utf_16le; +extern MSymbol Mcoding_utf_32; +extern MSymbol Mcoding_utf_32be; +extern MSymbol Mcoding_utf_32le; +extern MSymbol Mcoding_sjis; + +/* Parameter keys for mconv_define_coding (). */ +extern MSymbol Mtype; +extern MSymbol Mcharsets; +extern MSymbol Mflags; +extern MSymbol Mdesignation; +extern MSymbol Minvocation; +extern MSymbol Mcode_unit; +extern MSymbol Mbom; +extern MSymbol Mlittle_endian; + +/* Symbols representing coding system type. */ +extern MSymbol Mutf; +extern MSymbol Miso_2022; + +/* Symbols appearing in the value of Mfrag parameter. */ +extern MSymbol Mreset_at_eol; +extern MSymbol Mreset_at_cntl; +extern MSymbol Meight_bit; +extern MSymbol Mlong_form; +extern MSymbol Mdesignation_g0; +extern MSymbol Mdesignation_g1; +extern MSymbol Mdesignation_ctext; +extern MSymbol Mdesignation_ctext_ext; +extern MSymbol Mlocking_shift; +extern MSymbol Msingle_shift; +extern MSymbol Msingle_shift_7; +extern MSymbol Meuc_tw_shift; +extern MSymbol Miso_6429; +extern MSymbol Mrevision_number; +extern MSymbol Mfull_support; + +/* etc */ +extern MSymbol Mcoding; +extern MSymbol Mmaybe; + +/*** @ingroup m17nConv */ +/***en + @brief Codes that represent the result of code conversion. + + One of these values is set in @c MConverter-\>result. */ + +/***ja + @brief �������Ѵ��η�̤򼨤�������. + + �������ͤΤ�����Ĥ� @c MConverter-\>result �����ꤵ��롣 */ + +enum MConversionResult + { + /***en Code conversion is successful. */ + /***ja �������Ѵ�������. */ + MCONVERSION_RESULT_SUCCESS, + + /***en On decoding, the source contains an invalid byte. */ + /***ja �ǥ����ɻ����������������ʥХ��Ȥ��ޤޤ�Ƥ���. */ + MCONVERSION_RESULT_INVALID_BYTE, + + /***en On encoding, the source contains a character that cannot be + encoded by the specified coding system. */ + /***ja ���󥳡��ɻ�������Υ����ɷϤǥ��󥳡��ɤǤ��ʤ�ʸ�����������˴ޤޤ�Ƥ���. */ + MCONVERSION_RESULT_INVALID_CHAR, + + /***en On decoding, the source ends with an incomplete byte sequence. */ + /***ja �ǥ����ɻ����Դ����ʥХ�����ǥ�����������äƤ��롣*/ + MCONVERSION_RESULT_INSUFFICIENT_SRC, + + /***en On encoding, the destination is too short to store the result. */ + /***ja ���󥳡��ɻ�����̤��Ǽ�����ΰ褬û�������롣 */ + MCONVERSION_RESULT_INSUFFICIENT_DST, + + /***en An I/O error occurred in the conversion. */ + /***ja �������Ѵ���� I/O ���顼�������ä��� */ + MCONVERSION_RESULT_IO_ERROR + }; +/*=*/ + +/*** @ingroup m17nConv */ +/***en + @brief Structure to be used in code conversion. + + Structure to be used in code conversion. The first three members + are to control the conversion. */ + +/***ja + @brief �������Ѵ����Ѥ����빽¤��. + + �������Ѵ����Ѥ����빽¤�Ρ��ǽ�Σ��ĤΥ��Ф��Ѵ������椹�롣 + + @latexonly \IPAlabel{MConverter} @endlatexonly +*/ + +typedef struct +{ + /***en + Set the value to nonzero if the conversion should be lenient. + By default, the conversion is strict (i.e. not lenient). + + If the conversion is strict, the converter stops at the first + invalid byte (on decoding) or at the first character not + supported by the coding system (on encoding). If this happens, + @c MConverter-\>result is set to @c + MCONVERSION_RESULT_INVALID_BYTE or @c + MCONVERSION_RESULT_INVALID_CHAR accordingly. + + If the conversion is lenient, on decoding, an invalid byte is + kept per se, and on encoding, an invalid character is replaced + with "" (if the character is a Unicode character) or + with "" (otherwise). */ + + /***ja + ��̩���Ѵ���ɬ�פǤʤ������ͤ� 0 �ʳ��ˤ��롣 + �ǥե���ȤǤϡ��Ѵ��ϸ�̩�Ǥ��롣 + + �Ѵ�����̩�Ȥϡ��ǥ����ɤκݤˤϺǽ�������ʥХ��Ȥǥ���С������ߤޤ뤳�ȡ� + ���󥳡��ɤκݤˤ��Ѵ�����륳���ɷϤǥ��ݡ��Ȥ���ʤ��ǽ��ʸ���ǥ���С������ߤޤ뤳�Ȥ�ؤ��� + �����ξ�硢@c MConverter-\>result �Ϥ��줾�� @c + MCONVERSION_RESULT_INVALID_BYTE ��@c + MCONVERSION_RESULT_INVALID_CHAR �Ȥʤ롣 + + �Ѵ�����̩�Ǥʤ����ˤϡ��ǥ����ɤκݤ������ʥХ��ȤϤ��ΥХ��ȤΤޤ޻Ĥ롣 + �ޤ����󥳡��ɤκݤˤϡ�������ʸ���� Unicode ʸ���ξ��ˤ� "" + �ˡ������Ǥʤ����ˤ� "" ���֤��������롣 */ + + int lenient; + + /***en + Set the value to nonzero before decoding or encoding the last + block of the byte sequence or the character sequence + respectively. The value influences the conversion as below. + + On decoding, in the case that the last few bytes are too short + to form a valid byte sequence: + + If the value is nonzero, the conversion terminates by error + (MCONVERSION_RESULT_INVALID_BYTE) at the first byte of the + sequence. + + If the value is zero, the conversion terminates successfully. + Those bytes are stored in the converter as carryover and are + prepended to the byte sequence of the further conversion. + + On encoding, in the case that the coding system is context + dependent: + + If the value is nonzero, the conversion may produce a byte + sequence at the end to reset the context to the initial state + even if the source characters are zero. + + If the value is zero, the conversion never produce such a byte + sequence at the end. */ + +/***ja + + �Х�����ν�ü�Υ֥��å���ǥ����ɤ���ݡ��ޤ���ʸ����ν�ü�Υ֥��å��򥨥󥳡��ɤ���ݤϡ��ͤ� + 0 �ʳ��ˤ��롣�����ͤϰʲ��Τ褦���Ѵ��˱ƶ����롣 + + �ǥ����ǥ��󥰤κݤ˺Ǹ�ο��Х��Ȥ��������Х��ȥ��������󥹤��������ˤ�û�������硧 + + �ͤ� 0 �Ǥʤ���С��Ѵ��Ϥ��Υ��������󥹤κǽ�ΥХ��Ȥˤ����ơ����顼 + (MCONVERSION_RESULT_INVALID_BYTE) �ǽ��롣 + + �ͤ� 0 �ʤ�С��Ѵ����������ƽ��롣 + ����ο��Х��Ȥϥ���꡼�����ФȤ��ƥ���С������ݻ����졢�Ѵ���³����Ԥ��ݤ��Ѵ�����Х�����������դ����롣 + + ���󥳡��ǥ��󥰤κݤ˥����ɷϤ�ʸ̮��¸�ξ�硢 + + �ͤ� 0 �Ǥʤ���С�����ƥ����Ȥ�ǽ���᤹����ΥХ����󤬥�������ʸ���Ȥ������ʤ��Ѵ��η����������뤳�Ȥ����롣 + + �ͤ� 0 �ʤ�С����Τ褦�ʥХ��������������ʤ��� + + */ + + int last_block; + + /***en + If the value is nonzero, it specifies at most how many + characters to convert. */ + /***ja + 0 �Ǥʤ���С��Ѵ����������ʸ��������ꤹ�롣 + */ + + unsigned at_most; + + /***en + The following three members are to report the result of the + conversion. */ + /***ja + �ʲ��Σ��ĤΥ��Ф��Ѵ��η�̤�ɽ������Τ�ΤǤ��롣 */ + + /***en + Number of characters most recently decoded or encoded. */ + /***ja + �Ƕ�˥ǥ�����/���󥳡��ɤ��줿ʸ������ */ + + int nchars; + + /***en + Number of bytes recently decoded or encoded. */ + + /***ja + �Ƕ�˥ǥ�����/���󥳡��ɤ��줿�Х��ȿ��� */ + + int nbytes; + + /***en + Result code of the conversion. */ + + /***ja + �������Ѵ��η�̤򼨤������ɡ� */ + + enum MConversionResult result; + + /***en + Various information about the status of code conversion. The + contents depend on the type of coding system. It is assured + that @c status is aligned so that any type of casting is safe + and at least 256 bytes of memory space can be used. */ + + /***ja + �������Ѵ��ξ����˴ؤ����ξ������Ƥϥ����ɷϤΥ����פˤ�äưۤʤ롣 + @c status �ϤɤΤ褦�ʷ��ؤΥ��㥹�Ȥ��Ф��Ƥ�����ʤ褦�˥��ꥢ�饤�󤵤�Ƥ��ꡢ�ޤ�����256�Х��ȤΥ����ΰ褬�Ȥ���褦�ˤʤäƤ��롣 */ + + union { + void *ptr; + double dbl; + char c[256]; + } status; + + /***en + This member is for internally use only. An application program + should never touch it. */ + /***ja ���Υ��Ф�����Ū�˻��Ѥ��졢���ץꥱ�������ץ������Ͽ���ƤϤʤ�ʤ��� */ + void *internal_info; +} MConverter; +/*=*/ + +/*** @ingroup m17nConv */ +/***en + @brief Types of coding system. */ +/***ja + @brief �����ɷϤΥ�����. */ + +enum MCodingType + { + /***en + A coding system of this type supports charsets directly. + The dimension of each charset defines the length of bytes to + represent a single character of the charset, and a byte + sequence directly represents the code-point of a character. + The m17n library provides the default decoding and encoding + routines of this type. */ + + /***ja + ���Υ����פΥ����ɷϤ�ʸ�����åȤ�ľ�ܥ��ݡ��Ȥ��롣 + ��ʸ�����åȤμ����Ȥϡ�����ʸ�����åȤǰ�ʸ����ɽ�����뤿���ɬ�פʥХ��ȿ��Ǥ��ꡢ�Х������ʸ���Υ����ɥݥ���Ȥ�ľ��ɽ���� + m17n �饤�֥��Ϥ��Υ������ѤΥǥե���ȤΥ��󥳡��ɡ��ǥ����ɥ롼�ƥ�����󶡤��롣 */ + + MCODING_TYPE_CHARSET, + + /***en + A coding system of this type supports byte sequences of a + UTF (UTF-8, UTF-16, UTF-32) like structure. + The m17n library provides the default decoding and encoding + routines of this type. */ + + /***ja + ���Υ����פΥ����ɷϤϡ�UTF �� (UTF-8, UTF-16, UTF-32) �ΥХ�����򥵥ݡ��Ȥ��롣 + m17n �饤�֥��Ϥ��Υ������ѤΥǥե���ȤΥ��󥳡��ɡ��ǥ����ɥ롼�ƥ�����󶡤��롣 */ + + MCODING_TYPE_UTF, + + /***en + A coding system of this type supports byte sequences of an + ISO-2022 like structure. The details of each structure are + specified by @c MCodingInfoISO2022 . + The m17n library provides decoding and encoding routines of + this type. */ + + /***ja + ���Υ����פΥ����ɷϤϡ�ISO-2022 �ϤΥХ�����򥵥ݡ��Ȥ��롣 + �ƥ����ɷϤι�¤�ξܺ٤� @c MCodingInfoISO2022 �ǻ��ꤵ��롣 + m17n �饤�֥��Ϥ��Υ������ѤΥǥե���ȤΥ��󥳡��ɡ��ǥ����ɥ롼�ƥ�����󶡤��롣 */ + + MCODING_TYPE_ISO_2022, + + /***en + A coding system of this type is for byte sequences of + miscellaneous structures. + The m17n library does not provide decoding and encoding + routines of this type. They must be provided by the + application program. */ + + /***ja + ���Υ����פΥ����ɷϤϡ�����¾�ι�¤�ΥХ�����Τ���Τ�ΤǤ��롣 + m17n �饤�֥��Ϥ��Υ������ѤΥ��󥳡��ɡ��ǥ����ɥ롼�ƥ�����󶡤��ʤ��Τǡ����ץꥱ�������ץ������¦�ǽ�������ɬ�פ����롣 */ + + MCODING_TYPE_MISC + }; +/*=*/ + +/*** @ingroup m17nConv */ +/***en + @brief Bit-masks to specify the detail of coding system whose type is MCODING_TYPE_ISO_2022. */ +/***ja + @brief MCODING_TYPE_ISO_2022 �����פΥ����ɷϤξܺ٤�ɽ�魯�ӥåȥޥ���. */ + +enum MCodingFlagISO2022 + { + /***en + On encoding, reset the invocation and designation status to + initial at end of line. */ + /***ja ���󥳡��ɤκݡ������ǸƤӽФ� (invocation) �Ȼؼ� + (designation) �ξ��֤����ͤ��᤹�� */ + MCODING_ISO_RESET_AT_EOL = 0x1, + + /***en + On encoding, reset the invocation and designation status to + initial before any control codes. */ + /***ja + ���󥳡��ɤκݡ����٤Ƥ�����ʸ�������ǡ��ƤӽФ� + (invocation) �Ȼؼ� (designation) �ξ��֤����ͤ��᤹�� */ + MCODING_ISO_RESET_AT_CNTL = 0x2, + + /***en + Use the right graphic plane. */ + /***ja + �޷�ʸ������α�¦��Ȥ��� */ + MCODING_ISO_EIGHT_BIT = 0x4, + + /***en + Use the non-standard 4 bytes format for designation sequence + for charsets JISX0208-1978, GB2312, and JISX0208-1983. */ + /***ja + JISX0208-1978, GB2312, JISX0208-1983 + ��ʸ��������Ф���ؼ����������󥹤Ȥ��ơ���ɸ���4�Х��ȷ������Ѥ��롣 */ + + MCODING_ISO_LONG_FORM = 0x8, + + /***en + On encoding, unless explicitly specified, designate charsets + to G0. */ + /***ja + ���󥳡��ɤκݡ��ä˻��ꤵ��ʤ��¤ꡢʸ������� G0 + �˻ؼ����롣*/ + MCODING_ISO_DESIGNATION_G0 = 0x10, + + /***en + On encoding, unless explicitly specified, designate charsets + except for ASCII to G1. */ + /***ja + ���󥳡��ɤκݡ��ä˻��ꤵ��ʤ��¤ꡢASCII �ʳ���ʸ������� + G1 �˻ؼ����롣*/ + MCODING_ISO_DESIGNATION_G1 = 0x20, + + /***en + On encoding, unless explicitly specified, designate 94-chars + charsets to G0, 96-chars charsets to G1. */ + /***ja + ���󥳡��ɤκݡ��ä˻��ꤵ��ʤ��¤ꡢ94ʸ������� G0 + �ˡ�96ʸ������� G1 �˻ؼ����롣*/ + MCODING_ISO_DESIGNATION_CTEXT = 0x40, + + /***en + On encoding, encode such charsets not conforming to ISO-2022 + by ESC % / ..., and encode non-supported Unicode characters by + ESC % G ... ESC % @@ . On decoding, handle those escape + sequences. */ + /***ja + ���󥳡��ɤκݡ�ISO-2022 �˹��פ��ʤ�ʸ������� ESC % / ... + �ǥ��󥳡��ɤ��롣���ݡ��Ȥ���Ƥ��ʤ� Unicode ʸ���� ESC % G ... + ESC % @@ �ǥ��󥳡��ɤ��롣 + �ǥ����ɤκݡ������Υ��������ס��������󥹤��᤹�롣 */ + MCODING_ISO_DESIGNATION_CTEXT_EXT = 0x80, + + /***en + Use locking shift. */ + /***ja + ���å��󥰥��եȤ�Ȥ��� */ + MCODING_ISO_LOCKING_SHIFT = 0x100, + + /***en + Use single shift (SS2 (0x8E or ESC N), SS3 (0x8F or ESC O)). */ + /***ja + ���󥰥륷�ե� (SS2 (0x8E or ESC N), SS3 (0x8F or ESC O)) ��Ȥ��� */ + MCODING_ISO_SINGLE_SHIFT = 0x200, + + /***en + Use 7-bit single shift 2 (SS2 (0x19)). */ + /***ja + 7�ӥåȥ��󥰥륷�ե� 2 (SS2 (0x19)) ��Ȥ��� */ + MCODING_ISO_SINGLE_SHIFT_7 = 0x400, + + /***en + Use EUC-TW like special shifting. */ + /***ja + EUC-TW �������̤ʥ��եȤ�Ȥ��� */ + MCODING_ISO_EUC_TW_SHIFT = 0x800, + + /***en + Use ISO-6429 escape sequences to indicate direction. + Not yet implemented. */ + /***ja + ISO-6429 �Υ��������ץ��������󥹤�������ؼ����롣̤������ */ + MCODING_ISO_ISO6429 = 0x1000, + + /***en + On encoding, if a charset has revision number, produce escape + sequences to specify the number. */ + /***ja + ���󥳡��ɤκݡ�ʸ�����åȤ� revision number + ������Ф����ɽ�魯���������ץ��������󥹤��������롣 */ + MCODING_ISO_REVISION_NUMBER = 0x2000, + + /***en + Support all ISO-2022 charsets. */ + /***ja + ISO-2022 ����ʸ������򥵥ݡ��Ȥ��롣 */ + MCODING_ISO_FULL_SUPPORT = 0x3000, + + MCODING_ISO_FLAG_MAX + }; +/*=*/ + +/*** @ingroup m17nConv */ +/***en + @brief Structure for a coding system of type #MCODING_TYPE_ISO_2022. + + Structure for extra information about a coding system of type + MCODING_TYPE_ISO_2022. */ + +/***ja + @brief #MCODING_TYPE_ISO_2022 �����פΥ����ɷϤ�ɬ�פ��ղþ����ѹ�¤��. + + MCODING_TYPE_ISO_2022 �����פΥ����ɷϤ�ɬ�פ��ղþ����Ѥ��ݻ����뤿��ι�¤�Ρ� + + @latexonly \IPAlabel{MCodingInfoISO2022} @endlatexonly */ + +typedef struct +{ + /***en + Table of numbers of an ISO2022 code extension element invoked + to each graphic plane (Graphic Left and Graphic Right). -1 + means no code extension element is invoked to that plane. */ + + /***ja + �ƿ޷�ʸ���ΰ� (Graphic Left �� Graphic Right) �˸ƤӽФ���Ƥ��롢 + ISO2022 ����ĥ���Ǥ��ֹ�Υơ��֥롣-1 + �Ϥ����ΰ�ˤɤ�����ĥ���Ǥ�ƤӽФ���Ƥ��ʤ����Ȥ򼨤��� */ + + int initial_invocation[2]; + + /***en + Table of code extension elements. The Nth element corresponds + to the Nth charset in $CHARSET_NAMES, which is an argument given + to the mconv_define_coding () function. + + If an element value is 0..3, it specifies a graphic register + number to designate the corresponds charset. In addition, the + charset is initially designated to that graphic register. + + If the value is -4..-1, it specifies a graphic register number + 0..3 respectively to designate the corresponds charset. + Initially, the charset is not designated to any graphic + register. */ + + /***ja + ����ĥ���ǤΥơ��֥롣N���ܤ����Ǥϡ�$CHARSET_NAMES �� N + ���ܤ�ʸ�����åȤ��б����롣$CHARSET_NAMES �ϴؿ� + mconv_define_coding () �ΰ����Ȥʤ롣 + + �ͤ� 0..3 ���ä��顢�б�����ʸ�����åȤ� G0..G3 + �Τ��줾��˻ؼ����뤳�ȡ��ޤ�������֤Ǥ��Ǥ� G0..G3 + �˻ؼ�����Ƥ��뤳�Ȥ��̣���롣 + + �ͤ� -4..-1 ���ä��顢�б�����ʸ�����åȤ� G0..G3 + �Τ��줾��˻ؼ����뤳�ȡ�������������֤ǤϤɤ��ˤ�ؼ�����Ƥ��ʤ����Ȥ��̣���롣 + */ + + char designations[32]; + + /***en + Bitwise OR of @c enum @c MCodingFlagISO2022 . */ + + /***ja + @c enum @c MCodingFlagISO2022 �Υӥå�ñ�̤Ǥ����� OR */ + + unsigned flags; + +} MCodingInfoISO2022; +/*=*/ + +/*** @ingroup m17nConv */ +/***en + @brief Structure for extra information about a coding system of type #MCODING_TYPE_UTF. + */ + +/***ja + @brief #MCODING_TYPE_UTF �����פΥ����ɷϤ�ɬ�פ��ղþ����Ѥι�¤��. + + @latexonly \IPApage{MCodingInfoUTF} @endlatexonly + + @latexonly \IPAlabel{MCodingInfoUTF} @endlatexonly */ + +typedef struct +{ + /***en + Specify bits of a code unit. The value must be 8, 16, or 32. */ + /***ja + ������Ĺ�ʥӥåȿ��ˤλ��ꡣ�ͤ� 8, 16, 32 �Τ����줫�� */ + int code_unit_bits; + + /***en + Specify how to handle the heading BOM (byte order mark). The + value must be 0, 1, or 2. The meanings are as follows: + + 0: On decoding, check the first two byte. If they are BOM, + decide endian by them. If not, decide endian by the member @c + endian. On encoding, produce byte sequence according to + @c endian with heading BOM. + + 1: On decoding, do not handle the first two bytes as BOM, and + decide endian by @c endian. On encoding, produce byte sequence + according to @c endian without BOM. + + 2: On decoding, handle the first two bytes as BOM and decide + ending by them. On encoding, produce byte sequence according to + @c endian with heading BOM. + + If \ is 8, the value has no meaning. */ + + /***ja + ��Ƭ�� BOM (�Х��ȥ��������ޡ���) �μ�갷������ꤹ�롣�ͤ� 0, + 1, 2 �Τ����줫�Ǥ��ꡢ���줾��ΰ�̣�ϰʲ��Τ褦�ˤʤ롣 + + 0: �ǥ����ɤκݤ˺ǽ�� 2 �Х��Ȥ�Ĵ�٤롣�⤷���줬 BOM + �Ǥ���С�����ǥ�����򤽤��Ƚ�ꤹ�롣�����Ǥʤ���С����� @c + endian �˽��äƥ���ǥ��������ꤹ�롣���󥳡��ɤκݤˤ� @c + endian �˽��ä��Х��������Ƭ�� BOM �դ��������롣 + + 1: �ǥ����ɤκݡ��ǽ�� 2 �Х��Ȥ� BOM �Ȥ��ư��鷺������ǥ������ + @c endian ��Ƚ�ꤹ�롣���󥳡��ɤκݤˤϡ�BOM ����Ϥ����� + @c endian �˱������Х�������������롣 + + 2: �ǥ����ɤκݤ˺ǽ��2�Х��Ȥ� BOM�Ȥ��ư���������˽��äƥ���ǥ������Ƚ�ꤹ�롣 + ���󥳡��ɤκݤˤ� @c endian �˱������Х��������Ƭ�� BOM �դ����������롣 */ + int bom; + + /***en + Specify the endian type. The value must be 0 or 1. 0 means + little endian, and 1 means big endian. + + If \ is 8, the value has no meaning. */ + /***ja + ����ǥ�����Υ����פ���ꤹ�롣�ͤ� 0 �� 1 �Ǥ��ꡢ0 + �ʤ�Х�ȥ륨��ǥ�����1 �ʤ�Хӥå�����ǥ�����Ǥ��롣 + + \ �� 8 �ξ��ˤϡ������ͤϰ�̣������ʤ��� + */ + int endian; +} MCodingInfoUTF; +/*=*/ + +extern MSymbol mconv_define_coding (const char *name, MPlist *plist, + int (*resetter) (MConverter *), + int (*decoder) (const unsigned char *, int, + MText *, MConverter *), + int (*encoder) (MText *, int, int, + unsigned char *, int, + MConverter *), + void *extra_info); + +extern MSymbol mconv_resolve_coding (MSymbol symbol); + +extern int mconv_list_codings (MSymbol **symbols); + +extern MConverter *mconv_buffer_converter (MSymbol coding, + const unsigned char *buf, + int n); + +extern MConverter *mconv_stream_converter (MSymbol coding, FILE *fp); + +extern int mconv_reset_converter (MConverter *converter); + +extern void mconv_free_converter (MConverter *converter); + +extern MConverter *mconv_rebind_buffer (MConverter *converter, + const unsigned char *buf, int n); + +extern MConverter *mconv_rebind_stream (MConverter *converter, FILE *fp); + +extern MText *mconv_decode (MConverter *converter, MText *mt); + +MText *mconv_decode_buffer (MSymbol name, const unsigned char *buf, int n); + +MText *mconv_decode_stream (MSymbol name, FILE *fp); + +extern int mconv_encode (MConverter *converter, MText *mt); + +extern int mconv_encode_range (MConverter *converter, MText *mt, + int from, int to); + +extern int mconv_encode_buffer (MSymbol name, MText *mt, + unsigned char *buf, int n); + +extern int mconv_encode_stream (MSymbol name, MText *mt, FILE *fp); + +extern int mconv_getc (MConverter *converter); + +extern int mconv_ungetc (MConverter *converter, int c); + +extern int mconv_putc (MConverter *converter, int c); + +extern MText *mconv_gets (MConverter *converter, MText *mt); + +/* (S4) Locale related functions corresponding to libc functions */ +/*=*/ +/*** @ingroup m17nShell */ +/***en @defgroup m17nLocale Locale */ +/***ja @defgroup m17nLocale �������� */ +/*=*/ + +/*** @ingroup m17nLocale */ +/***en + @brief @c struct @c MLocale. + + The structure @c MLocale is used to hold information about name, + language, territory, modifier, codeset, and the corresponding + coding system of locales. + + The contents of this structure are implementation dependent. Its + internal structure is concealed from application programs. */ + +/***ja + @brief @c MLocale ��¤��. + + @c MLocale ��¤�Τϡ����������̾�������졢�ϰ衢��ǥ��ե������������ɥ��åȡ�������б����륳���ɷϤ˴ؤ��������ݻ����뤿����Ѥ����롣 + + ���ι�¤�Τ����Ƥϼ����˰�¸���롣 + ������¤�ϥ��ץꥱ�������ץ�����फ��ϸ����ʤ��� */ + +/*** + @seealso + mlocale_get_prop () */ + +typedef struct MLocale MLocale; + +/*=*/ + +extern MSymbol Miso639_1, Miso639_2; +extern MSymbol Mterritory; +extern MSymbol Mmodifier; +extern MSymbol Mcodeset; + +extern MPlist *mlanguage_list (void); + +extern MSymbol mlanguage_code (MSymbol language, int len); + +extern MPlist *mlanguage_name_list (MSymbol language, MSymbol target, + MSymbol script, MSymbol territory); + +extern MText *mlanguage_text (MSymbol language); + +extern MPlist *mscript_list (void); + +extern MPlist *mscript_language_list (MSymbol script); + +extern MSymbol mlanguage_name (MSymbol language); + +extern MLocale *mlocale_set (int category, const char *locale); + +extern MSymbol mlocale_get_prop (MLocale *locale, MSymbol key); + +extern int mtext_ftime (MText *mt, const char *format, const struct tm *tm, + MLocale *locale); + +extern MText *mtext_getenv (const char *name); + +extern int mtext_putenv (MText *mt); + +extern int mtext_coll (MText *mt1, MText *mt2); + +/* + * (9) Miscellaneous functions of libc level (not yet implemented) + */ + +/* +extern int mtext_width (MText *mt, int n); +extern MText *mtext_tolower (MText *mt); +extern MText *mtext_toupper (MText *mt); +*/ + +/* + * (10) Input method + */ +/*=*/ +/*** @ingroup m17nShell */ +/***en @defgroup m17nInputMethod Input Method (basic) */ +/***ja @defgroup m17nInputMethod ���ϥ᥽�å� (������ʬ) */ +/*=*/ + +/*** @addtogroup m17nInputMethod + @{ */ +/*=*/ +/* Struct forward declaration. */ +/*** + @brief See struct MInputMethod */ +typedef struct MInputMethod MInputMethod; +/*=*/ +/*** + @brief See struct MInputContext */ +typedef struct MInputContext MInputContext; +/*=*/ + +/***en + @brief Type of input method callback functions. + + This is the type of callback functions called from input method + drivers. $IC is a pointer to an input context, $COMMAND is a name + of callback for which the function is called. */ +/***ja + @brief ���ϥ᥽�åɥ�����Хå��ؿ��η����. + + ���ϥ᥽�åɤ���ƤФ�륳����Хå��ؿ��η��Ǥ��롣$IC + �����ϥ���ƥ����ȤؤΥݥ��󥿡�$COMMAND �ϴؿ����ƤФ�륳����Хå���̾���Ǥ��롣 */ + +typedef void (*MInputCallbackFunc) (MInputContext *ic, MSymbol command); +/*=*/ + +/***en + @brief Structure of input method driver. + + The type @c MInputDriver is the structure of an input method driver that + contains several functions to handle an input method. */ + +/***ja + @brief ���ϥɥ饤���ѹ�¤��. + + @c MInputDriver �ϡ����ϥ᥽�åɤ��갷���ؿ���ޤ����ϥ᥽�åɥɥ饤�Фι�¤�Τη��Ǥ��롣 */ + +typedef struct MInputDriver +{ + /***en + @brief Open an input method. + + This function opens the input method $IM. It is called from the + function minput_open_im () after all member of $IM but \ + set. If opening $IM succeeds, it returns 0. Otherwise, it + returns -1. The function can setup $IM->info to keep various + information that is referred by the other driver functions. */ + + /***ja + @brief ���ϥ᥽�åɤ򥪡��ץ󤹤�. + + ���δؿ��ϡ����ϥ᥽�å� $IM �򥪡��ץ󤹤롣$IM �� \ + �ʳ��������С������åȤ��줿��ǡ��ؿ� minput_open_im () + ����ƤФ�롣$IM �򥪡��ץ�Ǥ���� 0 �򡢤Ǥ��ʤ���� -1���֤��� + ���δؿ��� $IM->info + �����ꤷ�ơ�¾�Υɥ饤�дؿ����黲�Ȥ���������ݻ����뤳�Ȥ��Ǥ��롣 + */ + + int (*open_im) (MInputMethod *im); + + /***en + @brief Close an input method. + + This function closes the input method $IM. It is called from + the function minput_close_im (). It frees all memory allocated + for $IM->info (if any) after finishing all the tasks of closing + the input method. But, the other members of $IM should not be + touched. */ + + /***ja + @brief ���ϥ᥽�åɤ򥯥���������. + + ���δؿ��ϡ����ϥ᥽�å� $IM �򥯥��������롣�ؿ� + minput_close_im () ����ƤФ�롣 + ���ϥ᥽�åɤΥ������������٤ƽ�λ���������ǡ����δؿ���$IM->info + �˳�����Ƥ��Ƥ�������(�����)���٤Ƴ������롣 + ��������$IM ��¾�Υ��Ф˱ƶ���Ϳ���ƤϤʤ�ʤ��� + */ + + void (*close_im) (MInputMethod *im); + + /***en + @brief Create an input context. + + This function creates the input context $IC. It is called from + the function minput_create_ic () after all members of $IC but + \ are set. If creating $IC succeeds, it returns 0. + Otherwise, it returns -1. The function can setup $IC->info to + keep various information that is referred by the other driver + functions. */ + + /***ja + @brief ���ϥ���ƥ����Ȥ���������. + + ���δؿ������ϥ���ƥ����� $IC ���������롣 + $IC �� \ �ʳ��������С������åȤ��줿��ǡ��ؿ� + minput_create_ic () ����ƤФ�롣 + $IC �������Ǥ���� 0 �򡢤Ǥ��ʤ���� -1 ���֤��� + ���δؿ��� $IC->info �����ꤷ�ơ�¾�Υɥ饤�дؿ����黲�Ȥ���������ݻ����뤳�Ȥ��Ǥ��롣 */ + + + int (*create_ic) (MInputContext *ic); + + /***en + @brief Destroy an input context. + + This function is called from the function minput_destroy_ic () + and destroys the input context $IC. It frees all memory + allocated for $IC->info (if any) after finishing all the tasks + of destroying the input method. But, the other members of $IC + should not be touched. */ + + /***ja + @brief ���ϥ���ƥ����Ȥ��˲�����. + + �ؿ� minput_destroy_ic () ����ƤФ졢���ϥ���ƥ����� $IC + ���˲����롣���ϥ���ƥ����Ȥ��˲������٤ƽ�λ���������ǡ�$IC->info + �˳�����Ƥ��Ƥ�������(�����)���٤Ƴ������롣��������$IC + ��¾�Υ��Ф˱ƶ���Ϳ���ƤϤʤ�ʤ��� */ + + void (*destroy_ic) (MInputContext *ic); + + /***en + @brief Filter an input key. + + This function is called from the function minput_filter () and + filters an input key. $KEY and $ARG are the same as what given + to minput_filter (). + + The task of the function is to handle $KEY, update the internal + state of $IC. If $KEY is absorbed by the input method and no + text is produced, it returns 1. Otherwise, it returns 0. + + It may update $IC->status, $IC->preedit, $IC->cursor_pos, + $IC->ncandidates, $IC->candidates, and $IC->produced if that is + necessary for the member \. + + The meaning of $ARG depends on the input method river. See the + documentation of @c minput_default_driver and @c + minput_gui_driver for instance. */ + + /***ja + @brief ���ϥ�����ե��륿����. + + �ؿ� minput_filter () ����ƤФ졢���ϥ�����ե��륿���롣���� + $KEY, $ARG �ϴؿ� minput_filter () �Τ�Τ�Ʊ���� + + ���δؿ��� $KEY ���������$IC ���������֤򹹿����롣 $KEY + �����ϥ᥽�åɤ˵ۼ�����ƥƥ����Ȥ���������ʤ��ä����ˤϡ� + 1 ���֤��������Ǥʤ���� 0 ���֤��� + + ���� \ ��ɬ�פǤ���С�$IC->status, $IC->preedit, + $IC->cursor_pos, $IC->ncandidates, $IC->candidates, + $IC->produced �򹹿��Ǥ��롣 + + $ARG �ΰ�̣�����ϥ᥽�åɥɥ饤�Ф˰�¸���롣��� @c + minput_default_driver �ޤ��� @c minput_gui_driver + �������򻲾ȤΤ��ȡ� */ + + int (*filter) (MInputContext *ic, MSymbol key, void *arg); + + /***en + @brief Lookup a produced text in an input context. + + It is called from the function minput_lookup () and looks up a + produced text in the input context $IC. This function + concatenate a text produced by the input key $KEY (if any) to + M-text $MT. If $KEY was correctly handled by the input method + of $IC, it returns 0. Otherwise, it returns 1. + + The meaning of $ARG depends on the input method driver. See the + documentation of @c minput_default_driver and @c + minput_gui_driver for instance. */ + + /***ja + @brief ���ϥ���ƥ����Ȥ����������ƥ����Ȥγ���. + + �ؿ� minput_lookup () ����ƤФ졢���ϥ���ƥ����� $IC + �����������ƥ����Ȥ򸡺����롣���ϥ��� $KEY + �ˤ�ä����������ƥ����Ȥ�����С�M-text $MT ���ɲä��롣 $KEY + �����ϥ᥽�å� $IC �ˤ�ä����������������� 0 ���֤��������Ǥʤ���� 1 ���֤��� + + $ARG �ΰ�̣�����ϥ᥽�åɥɥ饤�Ф˰�¸���롣��� @c + minput_default_driver �ޤ��� @c minput_gui_driver �������򻲾Ȥ� + ���ȡ� */ + + int (*lookup) (MInputContext *ic, MSymbol key, void *arg, MText *mt); + + /***en + @brief List of callback functions. + + List of callback functions. Keys are one of + @b Minput_preedit_start, @b Minput_preedit_draw, + @b Minput_preedit_done, @b Minput_status_start, @b Minput_status_draw, + @b Minput_status_done, @b Minput_candidates_start, + @b Minput_candidates_draw, @b Minput_candidates_done, + @b Minput_set_spot, @b Minput_toggle, @b Minput_reset, + @b Minput_get_surrounding_text, @b Minput_delete_surrounding_text. + Values are functions of type #MInputCallbackFunc. */ + /***ja + @brief ������Хå��ؿ��Υꥹ��. + + ������Хå��ؿ��Υꥹ�ȡ������ϼ��Τ����줫�� + @b Minput_preedit_start, @b Minput_preedit_draw, + @b Minput_preedit_done, @b Minput_status_start, @b Minput_status_draw, + @b Minput_status_done, @b Minput_candidates_start, + @b Minput_candidates_draw, @b Minput_candidates_done, + @b Minput_set_spot, @b Minput_toggle, @b Minput_reset, + @b Minput_get_surrounding_text, @b Minput_delete_surrounding_text�� + �ͤ�#MInputCallbackFunc ���δؿ��� */ + MPlist *callback_list; + +} MInputDriver; +/*=*/ +/*** @} */ +/*=*/ + +extern MInputDriver minput_default_driver; + +extern MSymbol Minput_method; +extern MSymbol Minput_driver; + +extern MInputDriver *minput_driver; + +/** Symbols for callback commands. */ +extern MSymbol Minput_preedit_start; +extern MSymbol Minput_preedit_draw; +extern MSymbol Minput_preedit_done; +extern MSymbol Minput_status_start; +extern MSymbol Minput_status_draw; +extern MSymbol Minput_status_done; +extern MSymbol Minput_candidates_start; +extern MSymbol Minput_candidates_draw; +extern MSymbol Minput_candidates_done; +extern MSymbol Minput_set_spot; +extern MSymbol Minput_toggle; +extern MSymbol Minput_reset; +extern MSymbol Minput_get_surrounding_text; +extern MSymbol Minput_delete_surrounding_text; + +/** Symbols for special input key event. */ +extern MSymbol Minput_focus_move; +extern MSymbol Minput_focus_in; +extern MSymbol Minput_focus_out; + +/** Symbols describing input method command/variable. */ +extern MSymbol Minherited; +extern MSymbol Mcustomized; +extern MSymbol Mconfigured; + +/*** @addtogroup m17nInputMethod + @{ */ +/*=*/ +/***en + @brief Structure of input method. + + The type @c MInputMethod is the structure of input method + objects. */ +/***ja + @brief ���ϥ᥽�åɤι�¤��. + + @c MInputMethod �ϡ����ϥ᥽�åɥ��֥��������Ѥι�¤�Τη��Ǥ��롣 */ + +struct MInputMethod +{ + /***en Which language this input method is for. The value is @c + Mnil if the input method is foreign. */ + /***ja �ɤθ����Ѥ����ϥ᥽�åɤ��� + ���ϥ᥽�åɤ������Τ�ΤǤ�������ͤ� @c Mnil �� */ + MSymbol language; + + /***en Name of the input method. If the input method is foreign, it + must has a property of key @c Minput_driver and the value must be a + pointer to a proper input method driver. */ + /***ja ���ϥ᥽�åɤ�̾���������᥽�åɤǤ�����ˤϡ�@c + Minput_driver �򥭡��Ȥ���ץ��ѥƥ�������������ͤ�Ŭ�ڤ����ϥ᥽�åɥɥ饤�ФؤΥݥ��󥿤Ǥʤ��ƤϤʤ�ʤ���*/ + MSymbol name; + + /***en Input method driver of the input method. */ + /***ja �������ϥ᥽�å��Ѥ����ϥ᥽�åɥɥ饤�С� */ + MInputDriver driver; + + /***en The argument given to minput_open_im (). */ + /***ja minput_open_im () ���Ϥ��������� */ + void *arg; + + /***en Pointer to extra information that \.open_im () + setups. */ + /***ja \.open_im () �����ꤹ���ɲþ���ؤΥݥ��󥿡� */ + void *info; +}; + +/*=*/ + +/***en + @brief Bit-masks to specify how candidates of input method is changed. */ + +/***ja + @brief ���ϥ᥽�åɤ����ϸ��䤬�ɤ��ѹ����줿���򼨤��ӥåȥޥ���. */ + +enum MInputCandidatesChanged + { + MINPUT_CANDIDATES_LIST_CHANGED = 1, + MINPUT_CANDIDATES_INDEX_CHANGED = 2, + MINPUT_CANDIDATES_SHOW_CHANGED = 4, + MINPUT_CANDIDATES_CHANGED_MAX + }; + + +/*=*/ + +/***en + @brief Structure of input context. + + The type @c MInputContext is the structure of input context + objects. */ + +/***ja + @brief ���ϥ���ƥ������ѹ�¤��. + + @c MInputContext �ϡ����ϥ���ƥ����ȥ��֥��������Ѥι�¤�Τη��Ǥ��롣 */ + +struct MInputContext +{ + /***en Backward pointer to the input method. It is set up by the + function minput_create_ic (). */ + /***ja ���ϥ᥽�åɤؤεեݥ��󥿡��ؿ� minput_create_ic () + �ˤ�ä����ꤵ��롣 */ + MInputMethod *im; + + /***en M-text produced by the input method. It is set up by the + function minput_filter () . */ + /***ja ���ϥ᥽�åɤˤ�ä���������� M-text���ؿ� minput_filter () + �ˤ�ä����ꤵ��롣 */ + MText *produced; + + /***en Argument given to the function minput_create_ic (). */ + /***ja �ؿ� minput_create_ic () ���Ϥ��������� */ + void *arg; + + /***en Flag telling whether the input context is currently active or + inactive. The value is set to 1 (active) when the input context + is created. It is toggled by the function minput_toggle (). */ + /***ja ���ϥ���ƥ����Ȥ������ƥ��֤��ɤ����򼨤��ե饰�� + ���ϥ���ƥ����Ȥ��������줿�����Ǥ��ͤ� 1 �ʥ����ƥ��֡ˤǤ��ꡢ�ؿ� + minput_toggle () �ˤ�äƥȥ��뤵��롣 */ + int active; + + /***en Spot location and size of the input context. */ + /***ja ���ϥ���ƥ����ȤΥ��ݥåȤΰ��֤��礭��. */ + struct { + /***en X and Y coordinate of the spot. */ + /***ja ���ݥåȤ� X, Y ��ɸ. */ + int x, y; + + /***en Ascent and descent pixels of the line of the spot. */ + /***ja ���ݥåȤΥ�����Ȥȥǥ�����ȤΥԥ������. */ + int ascent, descent; + + /***en Font size for preedit text in 1/10 point. */ + /***ja preedit �ƥ������ѤΥե���ȥ����� (1/10 �ݥ����ñ��). */ + int fontsize; + + /***en M-text at the spot, or NULL. */ + /***ja ���ݥåȾ�� M-text���ޤ��� NULL. */ + MText *mt; + + /***en Character position in \ at the spot. */ + /***ja \ �ˤ����륹�ݥåȤ�ʸ������. */ + int pos; + } spot; + + /***en The usage of the following members depends on the input + method driver. The descriptions below are for the driver of an + internal input method. They are set by the function + \->driver.filter (). */ + /***ja �ʲ��Υ��Фλ���ˡ�����ϥ᥽�åɥɥ饤�Фˤ�äưۤʤ롣 + �ʲ��������ϡ��������ϥ᥽�å��Ѥ����ϥɥ饤�Ф��Ф����ΤǤ��롣 + �����ϴؿ� \->driver.filter () �ˤ�ä����ꤵ��롣 */ + + /***en Pointer to extra information that \->driver.create_ic () + setups. It is used to record the internal state of the input + context. */ + /***ja \->driver.create_ic () �����ꤹ���ɲþ���ؤΥݥ��󥿡� + ���ϥ���ƥ����Ȥ��������֤�Ͽ���뤿����Ѥ����롣 */ + void *info; + + /***en M-text describing the current status of the input + context. */ + /***ja ���ϥ���ƥ����Ȥθ��ߤξ��֤�ɽ�� M-text */ + MText *status; + + /***en The function \->driver.filter () sets the value to 1 when + it changes \. */ + /***ja �ؿ� \->driver.filter () �ϡ�\ ���Ѥ����ݤˤ����ͤ� 1 + �����ꤹ�롣 */ + int status_changed; + + /***en M-text containing the current preedit text. The function + \->driver.filter () sets the value. */ + /***ja ���ߤ� preedit �ƥ����Ȥ�ޤ� M-text���ؿ� + \->driver.filter () �ˤ�ä����ꤵ��롣 */ + MText *preedit; + + /***en The function \->driver.filter () sets the value to 1 when + it changes \. */ + /***ja �ؿ� \->driver.filter () �ϡ�\ ���Ѥ����ݤˤ����ͤ� + 1 �����ꤹ�롣 */ + int preedit_changed; + + /***en Cursor position of \. */ + /***ja \�Υ���������� */ + int cursor_pos; + + /***en The function \->driver.filter () sets the value to 1 when + it changes \. */ + /***ja �ؿ� \->driver.filter () �ϡ�\ ���Ѥ����ݤˤ����ͤ� + 1 �����ꤹ�롣 */ + int cursor_pos_changed; + + /***en Plist of the current candidate groups. Each element is an + M-text or a plist. If an element is an M-text (i.e. the key is Mtext), + candidates in that group are characters in the M-text. If it is + a plist (i.e. the key is Mplist), each element is an M-text, and + candidates in that group are those M-texts. */ + /***ja ���ߤθ��䥰�롼�פ� Plist �������Ǥ� M-text �� plist �Ǥ��롣 + ���Ǥ� M-text �ξ��ʥ����� Mtext �Ǥ�����ˤˤϡ����Υ��롼�פθ���Ϥ��� + M-text ��γ�ʸ���Ǥ��롣 ���Ǥ� plist �ξ��ʥ����� Mplist + �Ǥ�����ˤˤϡ����Υꥹ�Ȥγ����Ǥ� M-text �Ǥ��ꡢ����餬���Υ��롼�פθ���Ȥʤ롣 */ + MPlist *candidate_list; + + /***en Index number of the currently selected candidate in all the + candidates. The index of the first candidate is 0. If the + number is 8, and the first candidate group contains 7 + candidates, the currently selected candidate is the second element of the + second candidate group. */ + /***ja �������򤵤�Ƥ�����䤬��������Dz����ܤ���򼨤�����ǥå����� + �ǽ�θ���Υ���ǥå����� 0���ǽ�θ��䥰�롼�פ˼��Ĥθ��䤬�ޤޤ�Ƥ��ꡢ�����ͤ� + 8 �ʤ�С����ߤθ���������ܤθ��䥰�롼�פ������ܤ����ǤȤ������Ȥˤʤ롣 + */ + int candidate_index; + + /* @{ */ + /***en Start and the end positions of the preedit text where + \ corresponds to. */ + /***ja preedit �ƥ�������ǡ�\���б�����ǽ�ȺǸ�ΰ��֡� + */ + int candidate_from, candidate_to; + /* @} */ + + /***en Flag telling whether the current candidate group must be + shown or not. The function \->driver.filter () sets the + value to 1 when an input method required to show candidates, and + sets the value to 0 otherwise. */ + /***ja ���ߤθ��䥰�롼�פ�ɽ�����뤫�ɤ����򼨤��ե饰�� + �ؿ� \->driver.filter () �ϡ����ϥ᥽�åɤ������ɽ�����׵ᤷ���������ͤ� + 1 �ˡ�����ʳ��λ� 0 �����ꤹ�롣 */ + int candidate_show; + + /***en The function \->driver.filter () sets the value to bitwise + OR of @c enum @c MInputCandidatesChanged when it changed any of + the above members (\), and sets the value to 0 + otherwise. */ + /***ja �ؿ� \->driver.filter () �ϡ��嵭�Υ��� \ + �Σ��ĤǤ��ѹ������ݤˤϡ������ͤ� @c enum @c + MInputCandidatesChanged �Υӥå�ñ�̤Ǥ����� OR �����ꤹ�롣���� + �Ǥʤ���� 0 �����ꤹ�롣 */ + int candidates_changed; + + /***en Plist that can be freely used by \->driver functions. + The driver of internal input method uses it to exchange extra + arguments and result for callback functions. The function + \->driver.create_ic () sets this to an empty plist, and the + function \->driver.destroy_ic () frees it by using + m17n_object_unref (). */ + /***ja \->driver �δؿ����ˤ�äƼ�ͳ�˻��ѤǤ��� plist�� + �������ϥ᥽�å��ѥɥ饤�ФϤ���򥳡���Хå��ؿ��Ȥΰ��������� + �μ��Ϥ��˻��Ѥ��롣�ؿ� \->driver.create_ic () �Ϥ��� plist + ��������ꤹ�롣�ؿ�\->driver.destroy_ic () �� + m17n_object_unref () ���Ѥ��Ƥ��� plist ��������롣 */ + MPlist *plist; +}; + +/*=*/ +/*** @} */ +/*=*/ + +extern MInputMethod *minput_open_im (MSymbol language, MSymbol name, + void *arg); + +/*=*/ + +extern void minput_close_im (MInputMethod *im); + +extern MInputContext *minput_create_ic (MInputMethod *im, void *arg); + +extern void minput_destroy_ic (MInputContext *ic); + +extern int minput_filter (MInputContext *ic, MSymbol key, void *arg); + +extern int minput_lookup (MInputContext *ic, MSymbol key, void *arg, + MText *mt); +extern void minput_set_spot (MInputContext *ic, int x, int y, int ascent, + int descent, int fontsize, MText *mt, int pos); +extern void minput_toggle (MInputContext *ic); + +extern void minput_reset_ic (MInputContext *ic); + +extern MText *minput_get_description (MSymbol language, MSymbol name); + +extern MPlist *minput_get_title_icon (MSymbol language, MSymbol name); + +extern MPlist *minput_get_command (MSymbol language, MSymbol name, + MSymbol command); +extern int minput_config_command (MSymbol language, MSymbol name, + MSymbol command, MPlist *keyseq); +extern MPlist *minput_get_variable (MSymbol language, MSymbol name, + MSymbol variable); +extern int minput_config_variable (MSymbol language, MSymbol name, + MSymbol variable, MPlist *value); +extern char *minput_config_file (void); + +extern int minput_save_config (void); + +extern int minput_callback (MInputContext *ic, MSymbol command); + +/* obsolete functions */ +extern MPlist *minput_get_commands (MSymbol language, MSymbol name); + +extern int minput_assign_command_keys (MSymbol language, MSymbol name, + MSymbol command, MPlist *keys); +extern MPlist *minput_get_variables (MSymbol language, MSymbol name); + +extern int minput_set_variable (MSymbol language, MSymbol name, + MSymbol variable, void *value); + +extern MPlist *minput_parse_im_names (MText *mt); + +extern MPlist *minput_list (MSymbol lang); + +extern MInputMethod *mdebug_dump_im (MInputMethod *im, int indent); + +M17N_END_HEADER + +#endif /* _M17N_H_ */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/mlocale.h b/src/mlocale.h new file mode 100644 index 0000000..2d6f899 --- /dev/null +++ b/src/mlocale.h @@ -0,0 +1,30 @@ +/* mlocale.c -- header file for the locale module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_LOCAL_H_ +#define _M17N_LOCAL_H_ + +/** The current locales of each category. */ +extern MLocale *mlocale__collate, *mlocale__ctype; +extern MLocale *mlocale__messages, *mlocale__time; + +#endif /* _M17N_LOCAL_H_ */ diff --git a/src/mtext-lbrk.c b/src/mtext-lbrk.c new file mode 100644 index 0000000..3309d1f --- /dev/null +++ b/src/mtext-lbrk.c @@ -0,0 +1,441 @@ +/* mtext-lbrk.c -- line break + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include + +#include "config.h" +#include "m17n.h" +#include "m17n-misc.h" +#include "internal.h" +#include "mtext.h" + +enum LineBreakClass + { + LBC_OP, /* open */ + LBC_CL, /* close */ + LBC_QU, /* quotation */ + LBC_GL, /* glue */ + LBC_NS, /* no-start */ + LBC_EX, /* exclamation/interrogation */ + LBC_SY, /* Syntax (slash) */ + LBC_IS, /* infix (numeric) separator */ + LBC_PR, /* prefix */ + LBC_PO, /* postfix */ + LBC_NU, /* numeric */ + LBC_AL, /* alphabetic */ + LBC_ID, /* ideograph (atomic) */ + LBC_IN, /* inseparable */ + LBC_HY, /* hyphen */ + LBC_BA, /* break after */ + LBC_BB, /* break before */ + LBC_B2, /* break both */ + LBC_ZW, /* ZW space */ + LBC_CM, /* combining mark */ + LBC_WJ, /* word joiner */ + + /* used for 4.1 pair table */ + LBC_H2, /* Hamgul 2 Jamo Syllable */ + LBC_H3, /* Hangul 3 Jamo Syllable */ + LBC_JL, /* Jamo leading consonant */ + LBC_JV, /* Jamo vowel */ + LBC_JT, /* Jamo trailing consonant */ + + /* These are not handled in the pair tables. */ + LBC_SA, /* south (east) asian */ + LBC_SP, /* space */ + LBC_PS, /* paragraph and line separators */ + LBC_BK, /* hard break (newline) */ + LBC_CR, /* carriage return */ + LBC_LF, /* line feed */ + LBC_NL, /* next line */ + LBC_CB, /* contingent break opportunity */ + LBC_SG, /* surrogate */ + LBC_AI, /* ambiguous */ + LBC_XX, /* unknown */ + LBC_MAX + }; + +enum LineBreakAction + { + LBA_DIRECT = '_', + LBA_INDIRECT = '%', + LBA_COMBINING_INDIRECT = '#', + LBA_COMBINING_PROHIBITED = '@', + LBA_PROHIBITED = '^', + LBA_MAX + }; + +/* The pair table of line break actions. */ +static char *lba_pair_table[] = + /* OP GL SY PO ID BA ZW H2 JV + CL NS IS NU IN BB CM H3 JT + QU EX PR AL HY B2 WJ JL */ + { "^^^^^^^^^^^^^^^^^^^@^^^^^^", /* OP */ + "_^%%^^^^_%____%%__^#^_____", /* CL */ + "^^%%%^^^%%%%%%%%%%^#^%%%%%", /* QU */ + "%^%%%^^^%%%%%%%%%%^#^%%%%%", /* GL */ + "_^%%%^^^______%%__^#^_____", /* NS */ + "_^%%%^^^______%%__^#^_____", /* EX */ + "_^%%%^^^__%___%%__^#^_____", /* SY */ + "_^%%%^^^__%%__%%__^#^_____", /* IS */ + "%^%%%^^^__%%%_%%__^#^%%%%%", /* PR */ + "_^%%%^^^______%%__^#^_____", /* PO */ + "_^%%%^^^_%%%_%%%__^#^_____", /* NU */ + "_^%%%^^^__%%_%%%__^#^_____", /* AL */ + "_^%%%^^^_%___%%%__^#^_____", /* ID */ + "_^%%%^^^_____%%%__^#^_____", /* IN */ + "_^%%%^^^__%___%%__^#^_____", /* HY */ + "_^%%%^^^______%%__^#^_____", /* BA */ + "%^%%%^^^%%%%%%%%%%^#^%%%%%", /* BB */ + "_^%%%^^^______%%_^^#^_____", /* B2 */ + "__________________^_______", /* ZW */ + "_^%%%^^^__%%_%%%__^#^_____", /* CM */ + "%^%%%^^^%%%%%%%%%%^#^%%%%%", /* WJ */ + "_^%%%^^^_%___%%%__^#^___%%", /* H2 */ + "_^%%%^^^_%___%%%__^#^____%", /* H3 */ + "_^%%%^^^_%___%%%__^#^%%%%_", /* JL */ + "_^%%%^^^_%___%%%__^#^___%%", /* JV */ + "_^%%%^^^_%___%%%__^#^____%" /* JT */ + }; + +static MCharTable *lbc_table; + +/* Set LBC to enum LineBreakClass of the character at POS of MT + (length is LEN) while converting LBC_AI and LBC_XX to LBC_AL, + LBC_CB to LBC_B2, LBC_CR, LBC_LF, and LBC_NL to LBC_BK. If POS is + out of range, set LBC to LBC_BK. */ + +#define GET_LBC(LBC, MT, LEN, POS, OPTION) \ + do { \ + if ((POS) < 0 || (POS) >= (LEN)) \ + (LBC) = LBC_BK; \ + else \ + { \ + int c = mtext_ref_char ((MT), (POS)); \ + (LBC) = (enum LineBreakClass) mchartable_lookup (lbc_table, c); \ + if ((LBC) == LBC_NL) \ + (LBC) = LBC_BK; \ + else if ((LBC) == LBC_AI) \ + (LBC) = ((OPTION) & MTEXT_LBO_AI_AS_ID) ? LBC_ID : LBC_AL; \ + else if (! ((OPTION) & MTEXT_LBO_KOREAN_SP) \ + && (LBC) >= LBC_H2 && (LBC) <= LBC_JT) \ + (LBC) = LBC_AL; \ + else if ((LBC) == LBC_CB) \ + (LBC) = LBC_B2; \ + else if ((LBC) == LBC_XX) \ + (LBC) = LBC_AL; \ + } \ + } while (0) + + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/* External API */ + +/*** @addtogroup m17nMtext */ +/*** @{ */ +/*=*/ + +/***en + @brief Find a linebreak postion of an M-text. + + The mtext_line_break () function checks if position $POS is a + proper linebreak position of an M-text $MT according to the + algorithm of The Unicode Standard 4.0 UAX#14. It so, it returns + $POS. Otherwise, it returns a proper linebreak position before + $POS. + + If $OPTION is nonzero, it controls the algorithm by logical-or of + the members of #MTextLineBreakOption. + + If $AFTER is not NULL, a proper linebreak position after $POS is + stored there. */ + +int +mtext_line_break (MText *mt, int pos, int option, int *after) +{ + int break_before, break_after; + int len = mtext_len (mt); + enum LineBreakClass lbc; + enum LineBreakClass Blbc, Albc; /* B(efore) and A(fter) lbcs. */ + int Bpos, Apos; /* B(efore) and A(fter) positions. */ + enum LineBreakAction action; + + if (pos >= len) + { + /* The end of text is an explicit break position. */ + if (after) + *after = pos; + return pos; + } + + if (! lbc_table) + { + MSymbol key = mchar_define_property ("linebreak", Minteger); + + lbc_table = mchar_get_prop_table (key, NULL); + } + + GET_LBC (lbc, mt, len, pos, option); + Apos = pos; + Albc = lbc; + if (Albc == LBC_SP) + { + if (option & MTEXT_LBO_SP_CM) + { + GET_LBC (Albc, mt, len, Apos + 1, option); + Albc = (Albc == LBC_CM) ? LBC_ID : LBC_SP; + } + while (Albc == LBC_SP) + { + Apos--; + GET_LBC (Albc, mt, len, Apos, option); + } + } + if ((option & MTEXT_LBO_SP_CM) && (Albc == LBC_CM)) + { + Apos--; + GET_LBC (Albc, mt, len, Apos, option); + if (Albc == LBC_SP) + Albc = LBC_ID; + else + Apos++, Albc = LBC_CM; + } + + if (Albc == LBC_CR) + Albc = LBC_BK; + else if (Albc == LBC_LF) + { + GET_LBC (Albc, mt, len, Apos - 1, option); + if (Albc == LBC_CR) + Apos--; + Albc = LBC_BK; + } + else if (Albc == LBC_SA) + Albc = mtext__word_segment (mt, Apos, &Apos, NULL) > 0 ? LBC_BB : LBC_AL; + Bpos = Apos; + /* After exiting from the following loop, if Apos is positive, it is + the previous (including POS) break position. */ + while (Apos > 0) + { + int indirect; + int next = -1; + + /* Now Bpos == Apos. */ + do { + Bpos--; + GET_LBC (Blbc, mt, len, Bpos, option); + } while (Blbc == LBC_SP); + + if (Blbc == LBC_BK || Blbc == LBC_LF || Blbc == LBC_CR) + { + /* Explicit break. */ + break; + } + + indirect = Bpos + 1 < Apos; + + if (Blbc == LBC_CM) + { + do { + Bpos--; + GET_LBC (Blbc, mt, len, Bpos, option); + } while (Blbc == LBC_CM); + if ((option & MTEXT_LBO_SP_CM) && (Blbc == LBC_SP)) + Blbc = LBC_ID; + else if (Blbc == LBC_SP || Blbc == LBC_ZW + || Blbc == LBC_BK || Blbc == LBC_LF || Blbc == LBC_CR) + { + Blbc = LBC_AL; + Bpos++; + } + } + if (Blbc == LBC_SA) + { + mtext__word_segment (mt, Bpos, &next, NULL); + Blbc = LBC_AL; + } + + if (Albc != LBC_BK) + { + action = lba_pair_table[Blbc][Albc]; + if (action == LBA_DIRECT) + break; + else if (action == LBA_INDIRECT) + { + if (indirect) + break; + } + else if (action == LBA_COMBINING_INDIRECT) + { + if (indirect) + break; + } + } + if (next >= 0) + Apos = next, Albc = LBC_BB; + else + Apos = Bpos, Albc = Blbc; + } + break_before = Apos; + if (break_before > 0) + { + if (! after) + return break_before; + if (break_before == pos) + { + if (after) + *after = break_before; + return break_before; + } + } + + /* Now find a break position after POS. */ + break_after = 0; + Bpos = pos; + Blbc = lbc; + if (Blbc == LBC_CM) + { + do { + Bpos--; + GET_LBC (Blbc, mt, len, Bpos, option); + } while (Blbc == LBC_CM); + if (Blbc == LBC_SP || Blbc == LBC_ZW + || Blbc == LBC_BK || Blbc == LBC_LF || Blbc == LBC_CR) + { + if ((Blbc == LBC_SP) && (option & MTEXT_LBO_SP_CM)) + Blbc = LBC_ID; + else + Blbc = LBC_AL; + } + Bpos = pos; + } + if (Blbc == LBC_SA) + { + mtext__word_segment (mt, Bpos, NULL, &Bpos); + Blbc = LBC_AL; + } + else if (Blbc == LBC_SP) + { + if (option & MTEXT_LBO_SP_CM) + { + GET_LBC (Blbc, mt, len, Bpos + 1, option); + if (Blbc == LBC_CM) + Blbc = LBC_ID, Bpos++; + else + Blbc = LBC_SP; + } + while (Blbc == LBC_SP) + { + Bpos--; + GET_LBC (Blbc, mt, len, Bpos, option); + } + if (Bpos < 0) + Bpos = pos; + } + Apos = Bpos; + /* After exiting from the following loop, if Apos is positive, it is + the next break position. */ + while (1) + { + int indirect; + int next = -1; + + /* Now Bpos == Apos. */ + if (Blbc == LBC_LF || Blbc == LBC_BK || Blbc == LBC_CR) + { + Apos++; + if (Blbc == LBC_CR) + { + GET_LBC (Blbc, mt, len, Bpos + 1, option); + if (Blbc == LBC_LF) + Apos++; + } + break; + } + + do { + Apos++; + GET_LBC (Albc, mt, len, Apos, option); + } while (Albc == LBC_SP); + + if (Blbc == LBC_SP) + break; + + if (Apos == len) + /* Explicit break at the end of text. */ + break; + + indirect = Bpos + 1 < Apos; + + if (Albc == LBC_SA) + Albc = mtext__word_segment (mt, Apos, NULL, &next) ? LBC_BB : LBC_AL; + + action = lba_pair_table[Blbc][Albc]; + if (action == LBA_DIRECT) + /* Direct break at Apos. */ + break; + else if (action == LBA_INDIRECT) + { + if (indirect) + break; + } + else if (action == LBA_COMBINING_INDIRECT) + { + if (indirect) + { + if (option & MTEXT_LBO_SP_CM) + Apos--; + break; + } + } + if (next >= 0) + Bpos = next, Blbc = LBC_AL; + else + { + Bpos = Apos; + if (Albc != LBC_CM) + Blbc = Albc; + } + } + break_after = Apos; + if (after) + *after = break_after; + + return (break_before > 0 ? break_before : break_after); +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/mtext-wseg.c b/src/mtext-wseg.c new file mode 100644 index 0000000..98e7b29 --- /dev/null +++ b/src/mtext-wseg.c @@ -0,0 +1,420 @@ +/* mtext-wseg.c -- word segmentation + Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include + +#include "config.h" +#include "m17n-core.h" +#include "m17n-misc.h" +#include "internal.h" +#include "textprop.h" +#include "character.h" + +typedef struct _MWordseg_Function MWordseg_Function; + +struct _MWordseg_Function +{ + int initialized; + int (*init) (void); + void (*fini) (void); + int (*wseg) (MText *mt, int pos, int *from, int *to, + MWordseg_Function *wordseg); + MWordseg_Function *next; +}; + +static MWordseg_Function *wordseg_function_list; + +static MCharTable *wordseg_function_table; + +static int +generic_wordseg (MText *mt, int pos, int *from, int *to, + MWordseg_Function *wordseg) +{ + int len = mtext_nchars (mt); + int c = mtext_ref_char (mt, pos); + MSymbol category = mchar_get_prop (c, Mcategory); + char cathead = msymbol_name (category)[0]; + int in_word = (cathead == 'L' || cathead == 'M' || cathead == 'N'); + int beg, end; + + for (beg = pos; beg > 0; beg--) + { + c = mtext_ref_char (mt, beg - 1); + category = mchar_get_prop (c, Mcategory); + cathead = msymbol_name (category)[0]; + if (in_word != (cathead == 'L' || cathead == 'M' || cathead == 'N')) + break; + if (mchartable_lookup (wordseg_function_table, c) != wordseg) + break; + } + for (end = pos; end < len; end++) + { + c = mtext_ref_char (mt, end); + category = mchar_get_prop (c, Mcategory); + cathead = msymbol_name (category)[0]; + if (in_word != (cathead == 'L' || cathead == 'M' || cathead == 'N')) + break; + if (mchartable_lookup (wordseg_function_table, c) != wordseg) + break; + } + if (from) + *from = beg; + if (to) + *to = end; + return in_word; +} + +#ifdef HAVE_THAI_WORDSEG + +#define THAI_BEG 0x0E01 +#define THAI_END 0x0E6F + +static MSymbol M_thai_wordseg; + +/* We have libthai, wordcut, or wordcut-old. Each of them provides + the following three functions. */ + +static int thai_wordseg_init (void); +static void thai_wordseg_fini (void); +static MTextProperty *thai_wordseg_propertize (MText *mt, int pos, + int from, int to, + unsigned char *tis); + +#ifdef HAVE_LIBTHAI + +#include + +static int +thai_wordseg_init (void) +{ + return 0; +} + +static void +thai_wordseg_fini (void) +{ + return; +} + +static MTextProperty * +thai_wordseg_propertize (MText *mt, int pos, int from, int to, + unsigned char *tis) +{ + int len = to - from; + int *breaks = alloca ((sizeof (int)) * len); + int count = th_brk ((thchar_t *) tis, breaks, len); + MTextProperty *prop = NULL; + + if (count == 0) + { + prop = mtext_property (M_thai_wordseg, Mt, + MTEXTPROP_VOLATILE_WEAK | MTEXTPROP_NO_MERGE); + mtext_attach_property (mt, from, to, prop); + M17N_OBJECT_UNREF (prop); + } + else + { + int last, i; + MTextProperty *this; + + for (i = 0, last = from; i < count; i++) + { + this = mtext_property (M_thai_wordseg, Mt, + MTEXTPROP_VOLATILE_WEAK | MTEXTPROP_NO_MERGE); + mtext_attach_property (mt, last, from + breaks[i], this); + if (pos >= last && pos < from + breaks[i]) + prop = this; + M17N_OBJECT_UNREF (this); + last = from + breaks[i]; + } + if (last < to) + { + this = mtext_property (M_thai_wordseg, Mt, + MTEXTPROP_VOLATILE_WEAK | MTEXTPROP_NO_MERGE); + mtext_attach_property (mt, last, to, this); + if (pos >= last && pos < to) + prop = this; + M17N_OBJECT_UNREF (this); + } + } + + if (! prop) + mdebug_hook (); + return prop; +} + +#elif HAVE_WORDCUT + +#include + +static WcWordcut wordcut; +static WcWordVector *word_vector; + +static int +thai_wordseg_init (void) +{ + wc_wordcut_init (&wordcut); + return 0; +} + +static void +thai_wordseg_fini (void) +{ + if (word_vector) + wc_word_vector_delete (word_vector); + wc_wordcut_destroy (&wordcut); + return; +} + +static MTextProperty * +thai_wordseg_propertize (MText *mt, int pos, int from, int to, + unsigned char *tis) +{ + gulong i, count; + MTextProperty *prop = NULL; + + if (! word_vector) + word_vector = wc_word_vector_new (); + else + { + wc_word_vector_destroy (word_vector); + wc_word_vector_init (word_vector); + } + + wc_wordcut_cut (&wordcut, (gchar *) tis, (gint) (to - from), + word_vector); + count = wc_word_vector_get_count (word_vector); + for (i = 0; i < count; i++) + { + WcWord *word = wc_word_vector_get_word (word_vector, i); + + if (word->type != WC_WORDTYPE_DELETED) + { + MSymbol val = ((word->type == WC_WORDTYPE_DICTIONARY + || word->type == WC_WORDTYPE_WORDUNIT + || word->type == WC_WORDTYPE_JOINED) + ? Mt : Mnil); + MTextProperty *this + = mtext_property (M_thai_wordseg, val, + MTEXTPROP_VOLATILE_WEAK | MTEXTPROP_NO_MERGE); + + mtext_attach_property (mt, from, from + word->len, this); + if (pos >= from && pos < from + word->len) + prop = this; + M17N_OBJECT_UNREF (this); + from += word->len; + } + } + return prop; +} + +#else /* HAVE_WORDCUT_OLD */ + +#include + +static Wordcut wordcut; +static WordcutResult wordcut_result; +static int wordcut_result_used; + +static int +thai_wordseg_init (void) +{ + return (wordcut_init (&wordcut, WORDCUT_TDICT) == 0 ? 0 : -1); +} + +static void +thai_wordseg_fini (void) +{ + if (wordcut_result_used) + { + wordcut_result_close (&wordcut_result); + wordcut_result_used = 0; + } + wordcut_close (&wordcut); + return; +} + +static MTextProperty * +thai_wordseg_propertize (MText *mt, int pos, int from, int to, + unsigned char *tis) +{ + int i, last; + MTextProperty *prop = NULL; + + wordcut_cut (&wordcut, (char *) tis, &wordcut_result); + wordcut_result_used = 1; + for (i = 0, last = from; i < wordcut_result.count; i++) + { + MTextProperty *this; + + if (last < from + wordcut_result.start[i]) + { + this = mtext_property (M_thai_wordseg, Mnil, + MTEXTPROP_VOLATILE_WEAK); + mtext_attach_property (mt, last, from + wordcut_result.start[i], + this); + if (pos >= last && pos < from + wordcut_result.start[i]) + prop = this; + M17N_OBJECT_UNREF (this); + } + + this = mtext_property (M_thai_wordseg, Mt, + MTEXTPROP_VOLATILE_WEAK | MTEXTPROP_NO_MERGE); + last = from + wordcut_result.start[i]; + mtext_attach_property (mt, last, last + wordcut_result.offset[i], this); + if (pos >= last && pos < last + wordcut_result.offset[i]) + prop = this; + m17n_object_unref (this); + last += wordcut_result.offset[i]; + } + return prop; +} + +#endif /* not HAVE_LIBTHA, HAVE_WORDCUT nor HAVE_WORDCUT_OLD */ + +int +thai_wordseg (MText *mt, int pos, int *from, int *to, + MWordseg_Function *wordseg) +{ + MTextProperty *prop; + + /* It is assured that there's a Thai character at POS. */ + prop = mtext_get_property (mt, pos, M_thai_wordseg); + if (! prop) + { + /* TIS620 code sequence. */ + unsigned char *tis; + int len = mtext_nchars (mt); + int beg, end; + int c, i; + + for (beg = pos; beg > 0; beg--) + if ((c = mtext_ref_char (mt, beg - 1)) < THAI_BEG || c > THAI_END) + break; + for (end = pos + 1; end < len; end++) + if ((c = mtext_ref_char (mt, end)) < THAI_BEG || c > THAI_END) + break; + + /* Extra 1-byte for 0 terminating. */ + tis = alloca ((end - beg) + 1); + + for (i = beg; i < end; i++) + tis[i - beg] = 0xA1 + (mtext_ref_char (mt, i) - THAI_BEG); + tis[i - beg] = 0; + prop = thai_wordseg_propertize (mt, pos, beg, end, tis); + } + + if (from) + *from = MTEXTPROP_START (prop); + if (to) + *to = MTEXTPROP_END (prop); + return (MTEXTPROP_VAL (prop) == Mt); +} + +#endif /* HAVE_THAI_WORDSEG */ + + +/* Internal API */ + +void +mtext__wseg_fini () +{ + if (wordseg_function_list) + { + while (wordseg_function_list) + { + MWordseg_Function *next = wordseg_function_list->next; + + if (wordseg_function_list->initialized > 0 + && wordseg_function_list->fini) + wordseg_function_list->fini (); + free (wordseg_function_list); + wordseg_function_list = next; + } + M17N_OBJECT_UNREF (wordseg_function_table); + } +} + +/* Find word boundaries around POS of MT. Set *FROM to the word + boundary position at or previous to POS, and update *TO to the word + boundary position after POS. + + @return + If word boundaries were found successfully, return 1 (if + the character at POS is a part of a word) or 0 (otherwise). If the + operation was not successful, return -1 without setting *FROM and + *TO. */ + +int +mtext__word_segment (MText *mt, int pos, int *from, int *to) +{ + int c = mtext_ref_char (mt, pos); + MWordseg_Function *wordseg; + + if (! wordseg_function_table) + { + wordseg_function_table = mchartable (Mnil, NULL); + + MSTRUCT_CALLOC (wordseg, MERROR_MTEXT); + wordseg->wseg = generic_wordseg; + wordseg->next = wordseg_function_list; + wordseg_function_list = wordseg; + mchartable_set_range (wordseg_function_table, 0, MCHAR_MAX, wordseg); + +#ifdef HAVE_THAI_WORDSEG + MSTRUCT_CALLOC (wordseg, MERROR_MTEXT); + wordseg->init = thai_wordseg_init; + wordseg->fini = thai_wordseg_fini; + wordseg->wseg = thai_wordseg; + wordseg->next = wordseg_function_list; + wordseg_function_list = wordseg; + mchartable_set_range (wordseg_function_table, THAI_BEG, THAI_END, + wordseg); + M_thai_wordseg = msymbol (" thai-wordseg"); +#endif + } + + wordseg = mchartable_lookup (wordseg_function_table, c); + if (wordseg && wordseg->initialized >= 0) + { + if (! wordseg->initialized) + { + if (wordseg->init + && wordseg->init () < 0) + { + wordseg->initialized = -1; + return -1; + } + wordseg->initialized = 1; + } + return wordseg->wseg (mt, pos, from, to, wordseg); + } + return -1; +} + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ diff --git a/src/mtext.c b/src/mtext.c new file mode 100644 index 0000000..03b57f6 --- /dev/null +++ b/src/mtext.c @@ -0,0 +1,3679 @@ +/* mtext.c -- M-text module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nMtext + @brief M-text objects and API for them. + + In the m17n library, text is represented as an object called @e + M-text rather than as a C-string (char * or unsigned + char *). An M-text is a sequence of characters whose length + is equals to or more than 0, and can be coined from various + character sources, e.g. C-strings, files, character codes, etc. + + M-texts are more useful than C-strings in the following points. + + @li M-texts can handle mixture of characters of various scripts, + including all Unicode characters and more. This is an + indispensable facility when handling multilingual text. + + @li Each character in an M-text can have properties called @e text + @e properties. Text properties store various kinds of information + attached to parts of an M-text to provide application programs + with a unified view of those information. As rich information can + be stored in M-texts in the form of text properties, functions in + application programs can be simple. + + In addition, the library provides many functions to manipulate an + M-text just the same way as a C-string. */ + +/***ja + @addtogroup m17nMtext + + @brief M-text ���֥������ȤȤ���˴ؤ��� API. + + m17n �饤�֥��ϡ� C-string��char * �� unsigned + char *�ˤǤϤʤ� @e M-text �ȸƤ֥��֥������Ȥǥƥ����Ȥ�ɽ�����롣 + M-text ��Ĺ�� 0 �ʾ��ʸ����Ǥ��ꡢ���ʸ���������ʤ��Ȥ��� + C-string���ե����롢ʸ�����������ˤ�������Ǥ��롣 + + M-text �ˤϡ�C-string �ˤʤ��ʲ�����ħ�����롣 + + @li M-text ������¿���μ����ʸ����Ʊ���ˡ����ߤ����ơ�Ʊ���˰������Ȥ��Ǥ��롣 + Unicode �����Ƥ�ʸ���Ϥ�����󡢤��¿����ʸ���ޤǤⰷ�����Ȥ��Ǥ��롣 + �����¿����ƥ����Ȥ򰷤���Ǥ�ɬ�ܤε�ǽ�Ǥ��롣 + + @li M-text ��γ�ʸ���ϡ�@e �ƥ����ȥץ��ѥƥ� + �ȸƤФ��ץ��ѥƥ�������� + �ƥ����ȥץ��ѥƥ��ˤ�äơ��ƥ����Ȥγ����̤˴ؤ����͡��ʾ���� + M-text ����ݻ����뤳�Ȥ���ǽ�ˤʤ롣 + ���Τ��ᡢ�����ξ���򥢥ץꥱ�������ץ�������������Ū�˰������Ȥ���ǽ�ˤʤ롣 + �ޤ���M-text + ���Τ�˭�٤ʾ������Ĥ��ᡢ���ץꥱ�������ץ��������γƴؿ�����Dz����뤳�Ȥ��Ǥ��롣 + + �����m17n �饤�֥��ϡ� C-string + �����뤿����󶡤�����δؿ���Ʊ���Τ�Τ� M-text + �����뤿��˥��ݡ��Ȥ��Ƥ��롣 */ + +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include +#include +#include + +#include "m17n.h" +#include "m17n-misc.h" +#include "internal.h" +#include "textprop.h" +#include "character.h" +#include "mtext.h" +#include "plist.h" + +static M17NObjectArray mtext_table; + +static MSymbol M_charbag; + +/** Increment character position CHAR_POS and unit position UNIT_POS + so that they point to the next character in M-text MT. No range + check for CHAR_POS and UNIT_POS. */ + +#define INC_POSITION(mt, char_pos, unit_pos) \ + do { \ + int c; \ + \ + if ((mt)->format <= MTEXT_FORMAT_UTF_8) \ + { \ + c = (mt)->data[(unit_pos)]; \ + (unit_pos) += CHAR_UNITS_BY_HEAD_UTF8 (c); \ + } \ + else if ((mt)->format <= MTEXT_FORMAT_UTF_16BE) \ + { \ + c = ((unsigned short *) ((mt)->data))[(unit_pos)]; \ + \ + if ((mt)->format != MTEXT_FORMAT_UTF_16) \ + c = SWAP_16 (c); \ + (unit_pos) += CHAR_UNITS_BY_HEAD_UTF16 (c); \ + } \ + else \ + (unit_pos)++; \ + (char_pos)++; \ + } while (0) + + +/** Decrement character position CHAR_POS and unit position UNIT_POS + so that they point to the previous character in M-text MT. No + range check for CHAR_POS and UNIT_POS. */ + +#define DEC_POSITION(mt, char_pos, unit_pos) \ + do { \ + if ((mt)->format <= MTEXT_FORMAT_UTF_8) \ + { \ + unsigned char *p1 = (mt)->data + (unit_pos); \ + unsigned char *p0 = p1 - 1; \ + \ + while (! CHAR_HEAD_P (p0)) p0--; \ + (unit_pos) -= (p1 - p0); \ + } \ + else if ((mt)->format <= MTEXT_FORMAT_UTF_16BE) \ + { \ + int c = ((unsigned short *) ((mt)->data))[(unit_pos) - 1]; \ + \ + if ((mt)->format != MTEXT_FORMAT_UTF_16) \ + c = SWAP_16 (c); \ + (unit_pos) -= 2 - (c < 0xD800 || c >= 0xE000); \ + } \ + else \ + (unit_pos)--; \ + (char_pos)--; \ + } while (0) + +#define FORMAT_COVERAGE(fmt) \ + (fmt == MTEXT_FORMAT_UTF_8 ? MTEXT_COVERAGE_FULL \ + : fmt == MTEXT_FORMAT_US_ASCII ? MTEXT_COVERAGE_ASCII \ + : fmt >= MTEXT_FORMAT_UTF_32LE ? MTEXT_COVERAGE_FULL \ + : MTEXT_COVERAGE_UNICODE) + +/* Compoare sub-texts in MT1 (range FROM1 and TO1) and MT2 (range + FROM2 to TO2). */ + +static int +compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2) +{ + if (mt1->format == mt2->format + && (mt1->format <= MTEXT_FORMAT_UTF_8)) + { + unsigned char *p1, *pend1, *p2, *pend2; + int unit_bytes = UNIT_BYTES (mt1->format); + int nbytes; + int result; + + p1 = mt1->data + mtext__char_to_byte (mt1, from1) * unit_bytes; + pend1 = mt1->data + mtext__char_to_byte (mt1, to1) * unit_bytes; + + p2 = mt2->data + mtext__char_to_byte (mt2, from2) * unit_bytes; + pend2 = mt2->data + mtext__char_to_byte (mt2, to2) * unit_bytes; + + if (pend1 - p1 < pend2 - p2) + nbytes = pend1 - p1; + else + nbytes = pend2 - p2; + result = memcmp (p1, p2, nbytes); + if (result) + return result; + return ((pend1 - p1) - (pend2 - p2)); + } + for (; from1 < to1 && from2 < to2; from1++, from2++) + { + int c1 = mtext_ref_char (mt1, from1); + int c2 = mtext_ref_char (mt2, from2); + + if (c1 != c2) + return (c1 > c2 ? 1 : -1); + } + return (from2 == to2 ? (from1 < to1) : -1); +} + + +/* Return how many units are required in UTF-8 to represent characters + between FROM and TO of MT. */ + +static int +count_by_utf_8 (MText *mt, int from, int to) +{ + int n, c; + + for (n = 0; from < to; from++) + { + c = mtext_ref_char (mt, from); + n += CHAR_UNITS_UTF8 (c); + } + return n; +} + + +/* Return how many units are required in UTF-16 to represent + characters between FROM and TO of MT. */ + +static int +count_by_utf_16 (MText *mt, int from, int to) +{ + int n, c; + + for (n = 0; from < to; from++) + { + c = mtext_ref_char (mt, from); + n += CHAR_UNITS_UTF16 (c); + } + return n; +} + + +/* Insert text between FROM and TO of MT2 at POS of MT1. */ + +static MText * +insert (MText *mt1, int pos, MText *mt2, int from, int to) +{ + int pos_unit = POS_CHAR_TO_BYTE (mt1, pos); + int from_unit = POS_CHAR_TO_BYTE (mt2, from); + int new_units = POS_CHAR_TO_BYTE (mt2, to) - from_unit; + int unit_bytes; + + if (mt1->nchars == 0) + mt1->format = mt2->format, mt1->coverage = mt2->coverage; + else if (mt1->format != mt2->format) + { + /* Be sure to make mt1->format sufficient to contain all + characters in mt2. */ + if (mt1->format == MTEXT_FORMAT_UTF_8 + || mt1->format == MTEXT_FORMAT_UTF_32 + || (mt1->format == MTEXT_FORMAT_UTF_16 + && mt2->format <= MTEXT_FORMAT_UTF_16BE + && mt2->format != MTEXT_FORMAT_UTF_8)) + ; + else if (mt1->format == MTEXT_FORMAT_US_ASCII) + { + if (mt2->format == MTEXT_FORMAT_UTF_8) + mt1->format = MTEXT_FORMAT_UTF_8, mt1->coverage = mt2->coverage; + else if (mt2->format == MTEXT_FORMAT_UTF_16 + || mt2->format == MTEXT_FORMAT_UTF_32) + mtext__adjust_format (mt1, mt2->format); + else + mtext__adjust_format (mt1, MTEXT_FORMAT_UTF_8); + } + else + { + mtext__adjust_format (mt1, MTEXT_FORMAT_UTF_8); + pos_unit = POS_CHAR_TO_BYTE (mt1, pos); + } + } + + unit_bytes = UNIT_BYTES (mt1->format); + + if (mt1->format == mt2->format) + { + int pos_byte = pos_unit * unit_bytes; + int total_bytes = (mt1->nbytes + new_units) * unit_bytes; + int new_bytes = new_units * unit_bytes; + + if (total_bytes + unit_bytes > mt1->allocated) + { + mt1->allocated = total_bytes + unit_bytes; + if (mt1->data) + MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT); + else + MTABLE_CALLOC (mt1->data, mt1->allocated, MERROR_MTEXT); + } + memmove (mt1->data + pos_byte + new_bytes, mt1->data + pos_byte, + (mt1->nbytes - pos_unit + 1) * unit_bytes); + memcpy (mt1->data + pos_byte, mt2->data + from_unit * unit_bytes, + new_bytes); + } + else if (mt1->format == MTEXT_FORMAT_UTF_8) + { + unsigned char *p; + int total_bytes, i, c; + + new_units = count_by_utf_8 (mt2, from, to); + total_bytes = mt1->nbytes + new_units; + + if (total_bytes + 1 > mt1->allocated) + { + mt1->allocated = total_bytes + 1; + MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT); + } + p = mt1->data + pos_unit; + memmove (p + new_units, p, mt1->nbytes - pos_unit + 1); + for (i = from; i < to; i++) + { + c = mtext_ref_char (mt2, i); + p += CHAR_STRING_UTF8 (c, p); + } + } + else if (mt1->format == MTEXT_FORMAT_UTF_16) + { + unsigned short *p; + int total_bytes, i, c; + + new_units = count_by_utf_16 (mt2, from, to); + total_bytes = (mt1->nbytes + new_units) * USHORT_SIZE; + + if (total_bytes + USHORT_SIZE > mt1->allocated) + { + mt1->allocated = total_bytes + USHORT_SIZE; + MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT); + } + p = (unsigned short *) mt1->data + pos_unit; + memmove (p + new_units, p, + (mt1->nbytes - pos_unit + 1) * USHORT_SIZE); + for (i = from; i < to; i++) + { + c = mtext_ref_char (mt2, i); + p += CHAR_STRING_UTF16 (c, p); + } + } + else /* MTEXT_FORMAT_UTF_32 */ + { + unsigned int *p; + int total_bytes, i; + + new_units = to - from; + total_bytes = (mt1->nbytes + new_units) * UINT_SIZE; + + if (total_bytes + UINT_SIZE > mt1->allocated) + { + mt1->allocated = total_bytes + UINT_SIZE; + MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT); + } + p = (unsigned *) mt1->data + pos_unit; + memmove (p + new_units, p, + (mt1->nbytes - pos_unit + 1) * UINT_SIZE); + for (i = from; i < to; i++) + *p++ = mtext_ref_char (mt2, i); + } + + mtext__adjust_plist_for_insert + (mt1, pos, to - from, + mtext__copy_plist (mt2->plist, from, to, mt1, pos)); + mt1->nchars += to - from; + mt1->nbytes += new_units; + if (mt1->cache_char_pos > pos) + { + mt1->cache_char_pos += to - from; + mt1->cache_byte_pos += new_units; + } + + return mt1; +} + + +static MCharTable * +get_charbag (MText *mt) +{ + MTextProperty *prop = mtext_get_property (mt, 0, M_charbag); + MCharTable *table; + int i; + + if (prop) + { + if (prop->end == mt->nchars) + return ((MCharTable *) prop->val); + mtext_detach_property (prop); + } + + table = mchartable (Msymbol, (void *) 0); + for (i = mt->nchars - 1; i >= 0; i--) + mchartable_set (table, mtext_ref_char (mt, i), Mt); + prop = mtext_property (M_charbag, table, MTEXTPROP_VOLATILE_WEAK); + mtext_attach_property (mt, 0, mtext_nchars (mt), prop); + M17N_OBJECT_UNREF (prop); + return table; +} + + +/* span () : Number of consecutive chars starting at POS in MT1 that + are included (if NOT is Mnil) or not included (if NOT is Mt) in + MT2. */ + +static int +span (MText *mt1, MText *mt2, int pos, MSymbol not) +{ + int nchars = mtext_nchars (mt1); + MCharTable *table = get_charbag (mt2); + int i; + + for (i = pos; i < nchars; i++) + if ((MSymbol) mchartable_lookup (table, mtext_ref_char (mt1, i)) == not) + break; + return (i - pos); +} + + +static int +count_utf_8_chars (const void *data, int nitems) +{ + unsigned char *p = (unsigned char *) data; + unsigned char *pend = p + nitems; + int nchars = 0; + + while (p < pend) + { + int i, n; + + for (; p < pend && *p < 128; nchars++, p++); + if (p == pend) + return nchars; + if (! CHAR_HEAD_P_UTF8 (p)) + return -1; + n = CHAR_UNITS_BY_HEAD_UTF8 (*p); + if (p + n > pend) + return -1; + for (i = 1; i < n; i++) + if (CHAR_HEAD_P_UTF8 (p + i)) + return -1; + p += n; + nchars++; + } + return nchars; +} + +static int +count_utf_16_chars (const void *data, int nitems, int swap) +{ + unsigned short *p = (unsigned short *) data; + unsigned short *pend = p + nitems; + int nchars = 0; + int prev_surrogate = 0; + + for (; p < pend; p++) + { + int c = *p; + + if (swap) + c = SWAP_16 (c); + if (prev_surrogate) + { + if (c < 0xDC00 || c >= 0xE000) + /* Invalid surrogate */ + nchars++; + } + else + { + if (c >= 0xD800 && c < 0xDC00) + prev_surrogate = 1; + nchars++; + } + } + if (prev_surrogate) + nchars++; + return nchars; +} + + +static int +find_char_forward (MText *mt, int from, int to, int c) +{ + int from_byte = POS_CHAR_TO_BYTE (mt, from); + + if (mt->format <= MTEXT_FORMAT_UTF_8) + { + unsigned char *p = mt->data + from_byte; + + while (from < to && STRING_CHAR_ADVANCE_UTF8 (p) != c) from++; + } + else if (mt->format <= MTEXT_FORMAT_UTF_16BE) + { + unsigned short *p = (unsigned short *) (mt->data) + from_byte; + + if (mt->format == MTEXT_FORMAT_UTF_16) + while (from < to && STRING_CHAR_ADVANCE_UTF16 (p) != c) from++; + else if (c < 0x10000) + { + c = SWAP_16 (c); + while (from < to && *p != c) + { + from++; + p += ((*p & 0xFF) < 0xD8 || (*p & 0xFF) >= 0xE0) ? 1 : 2; + } + } + else if (c < 0x110000) + { + int c1 = (c >> 10) + 0xD800; + int c2 = (c & 0x3FF) + 0xDC00; + + c1 = SWAP_16 (c1); + c2 = SWAP_16 (c2); + while (from < to && (*p != c1 || p[1] != c2)) + { + from++; + p += ((*p & 0xFF) < 0xD8 || (*p & 0xFF) >= 0xE0) ? 1 : 2; + } + } + else + from = to; + } + else + { + unsigned *p = (unsigned *) (mt->data) + from_byte; + unsigned c1 = c; + + if (mt->format != MTEXT_FORMAT_UTF_32) + c1 = SWAP_32 (c1); + while (from < to && *p++ != c1) from++; + } + + return (from < to ? from : -1); +} + + +static int +find_char_backward (MText *mt, int from, int to, int c) +{ + int to_byte = POS_CHAR_TO_BYTE (mt, to); + + if (mt->format <= MTEXT_FORMAT_UTF_8) + { + unsigned char *p = mt->data + to_byte; + + while (from < to) + { + for (p--; ! CHAR_HEAD_P (p); p--); + if (c == STRING_CHAR (p)) + break; + to--; + } + } + else if (mt->format <= MTEXT_FORMAT_UTF_16LE) + { + unsigned short *p = (unsigned short *) (mt->data) + to_byte; + + if (mt->format == MTEXT_FORMAT_UTF_16) + { + while (from < to) + { + p--; + if (*p >= 0xDC00 && *p < 0xE000) + p--; + if (c == STRING_CHAR_UTF16 (p)) + break; + to--; + } + } + else if (c < 0x10000) + { + c = SWAP_16 (c); + while (from < to && p[-1] != c) + { + to--; + p -= ((p[-1] & 0xFF) < 0xD8 || (p[-1] & 0xFF) >= 0xE0) ? 1 : 2; + } + } + else if (c < 0x110000) + { + int c1 = (c >> 10) + 0xD800; + int c2 = (c & 0x3FF) + 0xDC00; + + c1 = SWAP_16 (c1); + c2 = SWAP_16 (c2); + while (from < to && (p[-1] != c2 || p[-2] != c1)) + { + to--; + p -= ((p[-1] & 0xFF) < 0xD8 || (p[-1] & 0xFF) >= 0xE0) ? 1 : 2; + } + } + } + else + { + unsigned *p = (unsigned *) (mt->data) + to_byte; + unsigned c1 = c; + + if (mt->format != MTEXT_FORMAT_UTF_32) + c1 = SWAP_32 (c1); + while (from < to && p[-1] != c1) to--, p--; + } + + return (from < to ? to - 1 : -1); +} + + +static void +free_mtext (void *object) +{ + MText *mt = (MText *) object; + + if (mt->plist) + mtext__free_plist (mt); + if (mt->data && mt->allocated >= 0) + free (mt->data); + M17N_OBJECT_UNREGISTER (mtext_table, mt); + free (object); +} + +/** Case handler (case-folding comparison and case conversion) */ + +/** Structure for an iterator used in case-fold comparison. */ + +struct casecmp_iterator { + MText *mt; + int pos; + MText *folded; + unsigned char *foldedp; + int folded_len; +}; + +static int +next_char_from_it (struct casecmp_iterator *it) +{ + int c, c1; + + if (it->folded) + { + c = STRING_CHAR_AND_BYTES (it->foldedp, it->folded_len); + return c; + } + + c = mtext_ref_char (it->mt, it->pos); + c1 = (int) mchar_get_prop (c, Msimple_case_folding); + if (c1 == 0xFFFF) + { + it->folded + = (MText *) mchar_get_prop (c, Mcomplicated_case_folding); + it->foldedp = it->folded->data; + c = STRING_CHAR_AND_BYTES (it->foldedp, it->folded_len); + return c; + } + + if (c1 >= 0) + c = c1; + return c; +} + +static void +advance_it (struct casecmp_iterator *it) +{ + if (it->folded) + { + it->foldedp += it->folded_len; + if (it->foldedp == it->folded->data + it->folded->nbytes) + it->folded = NULL; + } + if (! it->folded) + { + it->pos++; + } +} + +static int +case_compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2) +{ + struct casecmp_iterator it1, it2; + + it1.mt = mt1, it1.pos = from1, it1.folded = NULL; + it2.mt = mt2, it2.pos = from2, it2.folded = NULL; + + while (it1.pos < to1 && it2.pos < to2) + { + int c1 = next_char_from_it (&it1); + int c2 = next_char_from_it (&it2); + + if (c1 != c2) + return (c1 > c2 ? 1 : -1); + advance_it (&it1); + advance_it (&it2); + } + return (it2.pos == to2 ? (it1.pos < to1) : -1); +} + +static MCharTable *tricky_chars, *cased, *soft_dotted, *case_mapping; +static MCharTable *combining_class; + +/* Languages that require special handling in case-conversion. */ +static MSymbol Mlt, Mtr, Maz; + +static MText *gr03A3; +static MText *lt0049, *lt004A, *lt012E, *lt00CC, *lt00CD, *lt0128; +static MText *tr0130, *tr0049, *tr0069; + +static int +init_case_conversion () +{ + Mlt = msymbol ("lt"); + Mtr = msymbol ("tr"); + Maz = msymbol ("az"); + + gr03A3 = mtext (); + mtext_cat_char (gr03A3, 0x03C2); + + lt0049 = mtext (); + mtext_cat_char (lt0049, 0x0069); + mtext_cat_char (lt0049, 0x0307); + + lt004A = mtext (); + mtext_cat_char (lt004A, 0x006A); + mtext_cat_char (lt004A, 0x0307); + + lt012E = mtext (); + mtext_cat_char (lt012E, 0x012F); + mtext_cat_char (lt012E, 0x0307); + + lt00CC = mtext (); + mtext_cat_char (lt00CC, 0x0069); + mtext_cat_char (lt00CC, 0x0307); + mtext_cat_char (lt00CC, 0x0300); + + lt00CD = mtext (); + mtext_cat_char (lt00CD, 0x0069); + mtext_cat_char (lt00CD, 0x0307); + mtext_cat_char (lt00CD, 0x0301); + + lt0128 = mtext (); + mtext_cat_char (lt0128, 0x0069); + mtext_cat_char (lt0128, 0x0307); + mtext_cat_char (lt0128, 0x0303); + + tr0130 = mtext (); + mtext_cat_char (tr0130, 0x0069); + + tr0049 = mtext (); + mtext_cat_char (tr0049, 0x0131); + + tr0069 = mtext (); + mtext_cat_char (tr0069, 0x0130); + + if (! (cased = mchar_get_prop_table (msymbol ("cased"), NULL))) + return -1; + if (! (soft_dotted = mchar_get_prop_table (msymbol ("soft-dotted"), NULL))) + return -1; + if (! (case_mapping = mchar_get_prop_table (msymbol ("case-mapping"), NULL))) + return -1; + if (! (combining_class = mchar_get_prop_table (Mcombining_class, NULL))) + return -1; + + tricky_chars = mchartable (Mnil, 0); + mchartable_set (tricky_chars, 0x0049, (void *) 1); + mchartable_set (tricky_chars, 0x004A, (void *) 1); + mchartable_set (tricky_chars, 0x00CC, (void *) 1); + mchartable_set (tricky_chars, 0x00CD, (void *) 1); + mchartable_set (tricky_chars, 0x0128, (void *) 1); + mchartable_set (tricky_chars, 0x012E, (void *) 1); + mchartable_set (tricky_chars, 0x0130, (void *) 1); + mchartable_set (tricky_chars, 0x0307, (void *) 1); + mchartable_set (tricky_chars, 0x03A3, (void *) 1); + return 0; +} + +#define CASE_CONV_INIT(ret) \ + do { \ + if (! tricky_chars \ + && init_case_conversion () < 0) \ + MERROR (MERROR_MTEXT, ret); \ + } while (0) + +/* Replace the character at POS of MT with VAR and increment I and LEN. */ + +#define REPLACE(var) \ + do { \ + int varlen = var->nchars; \ + \ + mtext_replace (mt, pos, pos + 1, var, 0, varlen); \ + pos += varlen; \ + end += varlen - 1; \ + } while (0) + +/* Delete the character at POS of MT and decrement LEN. */ + +#define DELETE \ + do { \ + mtext_del (mt, pos, pos + 1); \ + end--; \ + } while (0) + +#define LOOKUP \ + do { \ + MPlist *pl = (MPlist *) mchartable_lookup (case_mapping, c); \ + \ + if (pl) \ + { \ + /* Lowercase is the 1st element. */ \ + MText *lower = MPLIST_VAL ((MPlist *) MPLIST_VAL (pl)); \ + int llen = mtext_nchars (lower); \ + \ + if (mtext_ref_char (lower, 0) != c || llen > 1) \ + { \ + mtext_replace (mt, pos, pos + 1, lower, 0, llen); \ + pos += llen; \ + end += llen - 1; \ + } \ + else \ + pos++; \ + } \ + else \ + pos++; \ + } while (0) + + +int +uppercase_precheck (MText *mt, int pos, int end) +{ + for (; pos < end; pos++) + if (mtext_ref_char (mt, pos) == 0x0307 && + (MSymbol) mtext_get_prop (mt, pos, Mlanguage) == Mlt) + return 1; + return 0; +} + +int +lowercase_precheck (MText *mt, int pos, int end) +{ + int c; + MSymbol lang; + + for (; pos < end; pos++) + { + c = mtext_ref_char (mt, pos); + + if ((int) mchartable_lookup (tricky_chars, c) == 1) + { + if (c == 0x03A3) + return 1; + + lang = mtext_get_prop (mt, pos, Mlanguage); + + if (lang == Mlt && + (c == 0x0049 || c == 0x004A || c == 0x012E)) + return 1; + + if ((lang == Mtr || lang == Maz) && + (c == 0x0307 || c == 0x0049)) + return 1; + } + } + return 0; +} + +#define CASED 1 +#define CASE_IGNORABLE 2 + +int +final_sigma (MText *mt, int pos) +{ + int i, len = mtext_len (mt); + int c; + + for (i = pos - 1; i >= 0; i--) + { + c = (int) mchartable_lookup (cased, mtext_ref_char (mt, i)); + if (c == -1) + c = 0; + if (c & CASED) + break; + if (! (c & CASE_IGNORABLE)) + return 0; + } + + if (i == -1) + return 0; + + for (i = pos + 1; i < len; i++) + { + c = (int) mchartable_lookup (cased, mtext_ref_char (mt, i)); + if (c == -1) + c = 0; + if (c & CASED) + return 0; + if (! (c & CASE_IGNORABLE)) + return 1; + } + + return 1; +} + +int +after_soft_dotted (MText *mt, int i) +{ + int c, class; + + for (i--; i >= 0; i--) + { + c = mtext_ref_char (mt, i); + if ((MSymbol) mchartable_lookup (soft_dotted, c) == Mt) + return 1; + class = (int) mchartable_lookup (combining_class, c); + if (class == 0 || class == 230) + return 0; + } + + return 0; +} + +int +more_above (MText *mt, int i) +{ + int class, len = mtext_len (mt); + + for (i++; i < len; i++) + { + class = (int) mchartable_lookup (combining_class, + mtext_ref_char (mt, i)); + if (class == 230) + return 1; + if (class == 0) + return 0; + } + + return 0; +} + +int +before_dot (MText *mt, int i) +{ + int c, class, len = mtext_len (mt); + + for (i++; i < len; i++) + { + c = mtext_ref_char (mt, i); + if (c == 0x0307) + return 1; + class = (int) mchartable_lookup (combining_class, c); + if (class == 230 || class == 0) + return 0; + } + + return 0; +} + +int +after_i (MText *mt, int i) +{ + int c, class; + + for (i--; i >= 0; i--) + { + c = mtext_ref_char (mt, i); + if (c == (int) 'I') + return 1; + class = (int) mchartable_lookup (combining_class, c); + if (class == 230 || class == 0) + return 0; + } + + return 0; +} + + +/* Internal API */ + +int +mtext__init () +{ + M17N_OBJECT_ADD_ARRAY (mtext_table, "M-text"); + M_charbag = msymbol_as_managing_key (" charbag"); + mtext_table.count = 0; + Mlanguage = msymbol ("language"); + return 0; +} + + +void +mtext__fini (void) +{ + mtext__wseg_fini (); +} + + +int +mtext__char_to_byte (MText *mt, int pos) +{ + int char_pos, byte_pos; + int forward; + + if (pos < mt->cache_char_pos) + { + if (mt->cache_char_pos == mt->cache_byte_pos) + return pos; + if (pos < mt->cache_char_pos - pos) + { + char_pos = byte_pos = 0; + forward = 1; + } + else + { + char_pos = mt->cache_char_pos; + byte_pos = mt->cache_byte_pos; + forward = 0; + } + } + else + { + if (mt->nchars - mt->cache_char_pos == mt->nbytes - mt->cache_byte_pos) + return (mt->cache_byte_pos + (pos - mt->cache_char_pos)); + if (pos - mt->cache_char_pos < mt->nchars - pos) + { + char_pos = mt->cache_char_pos; + byte_pos = mt->cache_byte_pos; + forward = 1; + } + else + { + char_pos = mt->nchars; + byte_pos = mt->nbytes; + forward = 0; + } + } + if (forward) + while (char_pos < pos) + INC_POSITION (mt, char_pos, byte_pos); + else + while (char_pos > pos) + DEC_POSITION (mt, char_pos, byte_pos); + mt->cache_char_pos = char_pos; + mt->cache_byte_pos = byte_pos; + return byte_pos; +} + +/* mtext__byte_to_char () */ + +int +mtext__byte_to_char (MText *mt, int pos_byte) +{ + int char_pos, byte_pos; + int forward; + + if (pos_byte < mt->cache_byte_pos) + { + if (mt->cache_char_pos == mt->cache_byte_pos) + return pos_byte; + if (pos_byte < mt->cache_byte_pos - pos_byte) + { + char_pos = byte_pos = 0; + forward = 1; + } + else + { + char_pos = mt->cache_char_pos; + byte_pos = mt->cache_byte_pos; + forward = 0; + } + } + else + { + if (mt->nchars - mt->cache_char_pos == mt->nbytes - mt->cache_byte_pos) + return (mt->cache_char_pos + (pos_byte - mt->cache_byte_pos)); + if (pos_byte - mt->cache_byte_pos < mt->nbytes - pos_byte) + { + char_pos = mt->cache_char_pos; + byte_pos = mt->cache_byte_pos; + forward = 1; + } + else + { + char_pos = mt->nchars; + byte_pos = mt->nbytes; + forward = 0; + } + } + if (forward) + while (byte_pos < pos_byte) + INC_POSITION (mt, char_pos, byte_pos); + else + while (byte_pos > pos_byte) + DEC_POSITION (mt, char_pos, byte_pos); + mt->cache_char_pos = char_pos; + mt->cache_byte_pos = byte_pos; + return char_pos; +} + +/* Estimated extra bytes that malloc will use for its own purpose on + each memory allocation. */ +#define MALLOC_OVERHEAD 4 +#define MALLOC_MININUM_BYTES 12 + +void +mtext__enlarge (MText *mt, int nbytes) +{ + nbytes += MAX_UTF8_CHAR_BYTES; + if (mt->allocated >= nbytes) + return; + if (nbytes < MALLOC_MININUM_BYTES) + nbytes = MALLOC_MININUM_BYTES; + while (mt->allocated < nbytes) + mt->allocated = mt->allocated * 2 + MALLOC_OVERHEAD; + MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT); +} + +int +mtext__takein (MText *mt, int nchars, int nbytes) +{ + if (mt->plist) + mtext__adjust_plist_for_insert (mt, mt->nchars, nchars, NULL); + mt->nchars += nchars; + mt->nbytes += nbytes; + mt->data[mt->nbytes] = 0; + return 0; +} + + +int +mtext__cat_data (MText *mt, unsigned char *p, int nbytes, + enum MTextFormat format) +{ + int nchars = -1; + + if (mt->format > MTEXT_FORMAT_UTF_8) + MERROR (MERROR_MTEXT, -1); + if (format == MTEXT_FORMAT_US_ASCII) + nchars = nbytes; + else if (format == MTEXT_FORMAT_UTF_8) + nchars = count_utf_8_chars (p, nbytes); + if (nchars < 0) + MERROR (MERROR_MTEXT, -1); + mtext__enlarge (mt, mtext_nbytes (mt) + nbytes + 1); + memcpy (MTEXT_DATA (mt) + mtext_nbytes (mt), p, nbytes); + mtext__takein (mt, nchars, nbytes); + return nchars; +} + +MText * +mtext__from_data (const void *data, int nitems, enum MTextFormat format, + int need_copy) +{ + MText *mt; + int nchars, nbytes, unit_bytes; + + if (format == MTEXT_FORMAT_US_ASCII) + { + const char *p = (char *) data, *pend = p + nitems; + + while (p < pend) + if (*p++ < 0) + MERROR (MERROR_MTEXT, NULL); + nchars = nbytes = nitems; + unit_bytes = 1; + } + else if (format == MTEXT_FORMAT_UTF_8) + { + if ((nchars = count_utf_8_chars (data, nitems)) < 0) + MERROR (MERROR_MTEXT, NULL); + nbytes = nitems; + unit_bytes = 1; + } + else if (format <= MTEXT_FORMAT_UTF_16BE) + { + if ((nchars = count_utf_16_chars (data, nitems, + format != MTEXT_FORMAT_UTF_16)) < 0) + MERROR (MERROR_MTEXT, NULL); + nbytes = USHORT_SIZE * nitems; + unit_bytes = USHORT_SIZE; + } + else /* MTEXT_FORMAT_UTF_32XX */ + { + nchars = nitems; + nbytes = UINT_SIZE * nitems; + unit_bytes = UINT_SIZE; + } + + mt = mtext (); + mt->format = format; + mt->coverage = FORMAT_COVERAGE (format); + mt->allocated = need_copy ? nbytes + unit_bytes : -1; + mt->nchars = nchars; + mt->nbytes = nitems; + if (need_copy) + { + MTABLE_MALLOC (mt->data, mt->allocated, MERROR_MTEXT); + memcpy (mt->data, data, nbytes); + mt->data[nbytes] = 0; + } + else + mt->data = (unsigned char *) data; + return mt; +} + + +void +mtext__adjust_format (MText *mt, enum MTextFormat format) +{ + int i, c; + + if (mt->nchars > 0) + switch (format) + { + case MTEXT_FORMAT_US_ASCII: + { + unsigned char *p = mt->data; + + for (i = 0; i < mt->nchars; i++) + *p++ = mtext_ref_char (mt, i); + mt->nbytes = mt->nchars; + mt->cache_byte_pos = mt->cache_char_pos; + break; + } + + case MTEXT_FORMAT_UTF_8: + { + unsigned char *p0, *p1; + + i = count_by_utf_8 (mt, 0, mt->nchars) + 1; + MTABLE_MALLOC (p0, i, MERROR_MTEXT); + mt->allocated = i; + for (i = 0, p1 = p0; i < mt->nchars; i++) + { + c = mtext_ref_char (mt, i); + p1 += CHAR_STRING_UTF8 (c, p1); + } + *p1 = '\0'; + free (mt->data); + mt->data = p0; + mt->nbytes = p1 - p0; + mt->cache_char_pos = mt->cache_byte_pos = 0; + break; + } + + default: + if (format == MTEXT_FORMAT_UTF_16) + { + unsigned short *p0, *p1; + + i = (count_by_utf_16 (mt, 0, mt->nchars) + 1) * USHORT_SIZE; + MTABLE_MALLOC (p0, i, MERROR_MTEXT); + mt->allocated = i; + for (i = 0, p1 = p0; i < mt->nchars; i++) + { + c = mtext_ref_char (mt, i); + p1 += CHAR_STRING_UTF16 (c, p1); + } + *p1 = 0; + free (mt->data); + mt->data = (unsigned char *) p0; + mt->nbytes = p1 - p0; + mt->cache_char_pos = mt->cache_byte_pos = 0; + break; + } + else + { + unsigned int *p; + + mt->allocated = (mt->nchars + 1) * UINT_SIZE; + MTABLE_MALLOC (p, mt->allocated, MERROR_MTEXT); + for (i = 0; i < mt->nchars; i++) + p[i] = mtext_ref_char (mt, i); + p[i] = 0; + free (mt->data); + mt->data = (unsigned char *) p; + mt->nbytes = mt->nchars; + mt->cache_byte_pos = mt->cache_char_pos; + } + } + mt->format = format; + mt->coverage = FORMAT_COVERAGE (format); +} + + +/* Find the position of a character at the beginning of a line of + M-Text MT searching backward from POS. */ + +int +mtext__bol (MText *mt, int pos) +{ + int byte_pos; + + if (pos == 0) + return pos; + byte_pos = POS_CHAR_TO_BYTE (mt, pos); + if (mt->format <= MTEXT_FORMAT_UTF_8) + { + unsigned char *p = mt->data + byte_pos; + + if (p[-1] == '\n') + return pos; + p--; + while (p > mt->data && p[-1] != '\n') + p--; + if (p == mt->data) + return 0; + byte_pos = p - mt->data; + return POS_BYTE_TO_CHAR (mt, byte_pos); + } + else if (mt->format <= MTEXT_FORMAT_UTF_16BE) + { + unsigned short *p = ((unsigned short *) (mt->data)) + byte_pos; + unsigned short newline = (mt->format == MTEXT_FORMAT_UTF_16 + ? 0x0A00 : 0x000A); + + if (p[-1] == newline) + return pos; + p--; + while (p > (unsigned short *) (mt->data) && p[-1] != newline) + p--; + if (p == (unsigned short *) (mt->data)) + return 0; + byte_pos = p - (unsigned short *) (mt->data); + return POS_BYTE_TO_CHAR (mt, byte_pos);; + } + else + { + unsigned *p = ((unsigned *) (mt->data)) + byte_pos; + unsigned newline = (mt->format == MTEXT_FORMAT_UTF_32 + ? 0x0A000000 : 0x0000000A); + + if (p[-1] == newline) + return pos; + p--, pos--; + while (p > (unsigned *) (mt->data) && p[-1] != newline) + p--, pos--; + return pos; + } +} + + +/* Find the position of a character at the end of a line of M-Text MT + searching forward from POS. */ + +int +mtext__eol (MText *mt, int pos) +{ + int byte_pos; + + if (pos == mt->nchars) + return pos; + byte_pos = POS_CHAR_TO_BYTE (mt, pos); + if (mt->format <= MTEXT_FORMAT_UTF_8) + { + unsigned char *p = mt->data + byte_pos; + unsigned char *endp; + + if (*p == '\n') + return pos + 1; + p++; + endp = mt->data + mt->nbytes; + while (p < endp && *p != '\n') + p++; + if (p == endp) + return mt->nchars; + byte_pos = p + 1 - mt->data; + return POS_BYTE_TO_CHAR (mt, byte_pos); + } + else if (mt->format <= MTEXT_FORMAT_UTF_16BE) + { + unsigned short *p = ((unsigned short *) (mt->data)) + byte_pos; + unsigned short *endp; + unsigned short newline = (mt->format == MTEXT_FORMAT_UTF_16 + ? 0x0A00 : 0x000A); + + if (*p == newline) + return pos + 1; + p++; + endp = (unsigned short *) (mt->data) + mt->nbytes; + while (p < endp && *p != newline) + p++; + if (p == endp) + return mt->nchars; + byte_pos = p + 1 - (unsigned short *) (mt->data); + return POS_BYTE_TO_CHAR (mt, byte_pos); + } + else + { + unsigned *p = ((unsigned *) (mt->data)) + byte_pos; + unsigned *endp; + unsigned newline = (mt->format == MTEXT_FORMAT_UTF_32 + ? 0x0A000000 : 0x0000000A); + + if (*p == newline) + return pos + 1; + p++, pos++; + endp = (unsigned *) (mt->data) + mt->nbytes; + while (p < endp && *p != newline) + p++, pos++; + return pos; + } +} + +int +mtext__lowercase (MText *mt, int pos, int end) +{ + int opos = pos; + int c; + MText *orig = NULL; + MSymbol lang; + + if (lowercase_precheck (mt, pos, end)) + orig = mtext_dup (mt); + + for (; pos < end; opos++) + { + c = mtext_ref_char (mt, pos); + lang = (MSymbol) mtext_get_prop (mt, pos, Mlanguage); + + if (c == 0x03A3 && final_sigma (orig, opos)) + REPLACE (gr03A3); + + else if (lang == Mlt) + { + if (c == 0x00CC) + REPLACE (lt00CC); + else if (c == 0x00CD) + REPLACE (lt00CD); + else if (c == 0x0128) + REPLACE (lt0128); + else if (orig && more_above (orig, opos)) + { + if (c == 0x0049) + REPLACE (lt0049); + else if (c == 0x004A) + REPLACE (lt004A); + else if (c == 0x012E) + REPLACE (lt012E); + else + LOOKUP; + } + else + LOOKUP; + } + + else if (lang == Mtr || lang == Maz) + { + if (c == 0x0130) + REPLACE (tr0130); + else if (c == 0x0307 && after_i (orig, opos)) + DELETE; + else if (c == 0x0049 && ! before_dot (orig, opos)) + REPLACE (tr0049); + else + LOOKUP; + } + + else + LOOKUP; + } + + if (orig) + m17n_object_unref (orig); + + return end; +} + +int +mtext__titlecase (MText *mt, int pos, int end) +{ + int opos = pos; + int c; + MText *orig = NULL; + MSymbol lang; + MPlist *pl; + + /* Precheck for titlecase is identical to that for uppercase. */ + if (uppercase_precheck (mt, pos, end)) + orig = mtext_dup (mt); + + for (; pos < end; opos++) + { + c = mtext_ref_char (mt, pos); + lang = (MSymbol) mtext_get_prop (mt, pos, Mlanguage); + + if ((lang == Mtr || lang == Maz) && c == 0x0069) + REPLACE (tr0069); + + else if (lang == Mlt && c == 0x0307 && after_soft_dotted (orig, opos)) + DELETE; + + else if ((pl = (MPlist *) mchartable_lookup (case_mapping, c))) + { + /* Titlecase is the 2nd element. */ + MText *title + = (MText *) mplist_value (mplist_next (mplist_value (pl))); + int tlen = mtext_len (title); + + if (mtext_ref_char (title, 0) != c || tlen > 1) + { + mtext_replace (mt, pos, pos + 1, title, 0, tlen); + pos += tlen; + end += tlen - 1; + } + + else + pos++; + } + + else + pos++; + } + + if (orig) + m17n_object_unref (orig); + + return end; +} + +int +mtext__uppercase (MText *mt, int pos, int end) +{ + int opos = pos; + int c; + MText *orig = NULL; + MSymbol lang; + MPlist *pl; + + CASE_CONV_INIT (-1); + + if (uppercase_precheck (mt, 0, end)) + orig = mtext_dup (mt); + + for (; pos < end; opos++) + { + c = mtext_ref_char (mt, pos); + lang = (MSymbol) mtext_get_prop (mt, pos, Mlanguage); + + if (lang == Mlt && c == 0x0307 && after_soft_dotted (orig, opos)) + DELETE; + + else if ((lang == Mtr || lang == Maz) && c == 0x0069) + REPLACE (tr0069); + + else + { + if ((pl = (MPlist *) mchartable_lookup (case_mapping, c)) != NULL) + { + MText *upper; + int ulen; + + /* Uppercase is the 3rd element. */ + upper = (MText *) mplist_value (mplist_next (mplist_next (mplist_value (pl)))); + ulen = mtext_len (upper); + + if (mtext_ref_char (upper, 0) != c || ulen > 1) + { + mtext_replace (mt, pos, pos + 1, upper, 0, ulen); + pos += ulen; + end += ulen - 1; + } + + else + pos++; + } + + else /* pl == NULL */ + pos++; + } + } + + if (orig) + m17n_object_unref (orig); + + return end; +} + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/* External API */ + +#ifdef WORDS_BIGENDIAN +const enum MTextFormat MTEXT_FORMAT_UTF_16 = MTEXT_FORMAT_UTF_16BE; +#else +const enum MTextFormat MTEXT_FORMAT_UTF_16 = MTEXT_FORMAT_UTF_16LE; +#endif + +#ifdef WORDS_BIGENDIAN +const int MTEXT_FORMAT_UTF_32 = MTEXT_FORMAT_UTF_32BE; +#else +const int MTEXT_FORMAT_UTF_32 = MTEXT_FORMAT_UTF_32LE; +#endif + +/*** @addtogroup m17nMtext */ +/*** @{ */ +/*=*/ + +/***en The symbol whose name is "language". */ +/***ja "language" �Ȥ���̾������ĥ���ܥ�. */ +MSymbol Mlanguage; + +/*=*/ + +/***en + @brief Allocate a new M-text. + + The mtext () function allocates a new M-text of length 0 and + returns a pointer to it. The allocated M-text will not be freed + unless the user explicitly does so with the m17n_object_unref () + function. */ + +/***ja + @brief ������M-text�������Ƥ�. + + �ؿ� mtext () �ϡ�Ĺ�� 0 �ο����� M-text + �������ơ�����ؤΥݥ��󥿤��֤���������Ƥ�줿 M-text �ϡ��ؿ� + m17n_object_unref () �ˤ�äƥ桼��������Ū�˹Ԥʤ�ʤ��¤ꡢ��������ʤ��� + + @latexonly \IPAlabel{mtext} @endlatexonly */ + +/*** + @seealso + m17n_object_unref () */ + +MText * +mtext () +{ + MText *mt; + + M17N_OBJECT (mt, free_mtext, MERROR_MTEXT); + mt->format = MTEXT_FORMAT_US_ASCII; + mt->coverage = MTEXT_COVERAGE_ASCII; + M17N_OBJECT_REGISTER (mtext_table, mt); + return mt; +} + +/***en + @brief Allocate a new M-text with specified data. + + The mtext_from_data () function allocates a new M-text whose + character sequence is specified by array $DATA of $NITEMS + elements. $FORMAT specifies the format of $DATA. + + When $FORMAT is either #MTEXT_FORMAT_US_ASCII or + #MTEXT_FORMAT_UTF_8, the contents of $DATA must be of the type @c + unsigned @c char, and $NITEMS counts by byte. + + When $FORMAT is either #MTEXT_FORMAT_UTF_16LE or + #MTEXT_FORMAT_UTF_16BE, the contents of $DATA must be of the type + @c unsigned @c short, and $NITEMS counts by unsigned short. + + When $FORMAT is either #MTEXT_FORMAT_UTF_32LE or + #MTEXT_FORMAT_UTF_32BE, the contents of $DATA must be of the type + @c unsigned, and $NITEMS counts by unsigned. + + The character sequence of the M-text is not modifiable. + The contents of $DATA must not be modified while the M-text is alive. + + The allocated M-text will not be freed unless the user explicitly + does so with the m17n_object_unref () function. Even in that case, + $DATA is not freed. + + @return + If the operation was successful, mtext_from_data () returns a + pointer to the allocated M-text. Otherwise it returns @c NULL and + assigns an error code to the external variable #merror_code. */ +/***ja + @brief ����Υǡ����򸵤˿����� M-text �������Ƥ�. + + �ؿ� mtext_from_data () �ϡ����ǿ� $NITEMS ������ $DATA + �ǻ��ꤵ�줿ʸ�������Ŀ����� M-text �������Ƥ롣$FORMAT �� $DATA + �Υե����ޥåȤ򼨤��� + + $FORMAT �� #MTEXT_FORMAT_US_ASCII �� #MTEXT_FORMAT_UTF_8 �ʤ�С� + $DATA �����Ƥ� @c unsigned @c char ���Ǥ��ꡢ$NITEMS + �ϥХ���ñ�̤�ɽ����Ƥ��롣 + + $FORMAT �� #MTEXT_FORMAT_UTF_16LE �� #MTEXT_FORMAT_UTF_16BE �ʤ�С� + $DATA �����Ƥ� @c unsigned @c short ���Ǥ��ꡢ$NITEMS �� unsigned + short ñ�̤Ǥ��롣 + + $FORMAT �� #MTEXT_FORMAT_UTF_32LE �� #MTEXT_FORMAT_UTF_32BE �ʤ�С� + $DATA �����Ƥ� @c unsigned ���Ǥ��ꡢ$NITEMS �� unsigned ñ�̤Ǥ��롣 + + ������Ƥ�줿 M-text ��ʸ������ѹ��Ǥ��ʤ���$DATA �����Ƥ� + M-text ��ͭ���ʴ֤��ѹ����ƤϤʤ�ʤ��� + + ������Ƥ�줿 M-text �ϡ��ؿ� m17n_object_unref () + �ˤ�äƥ桼��������Ū�˹Ԥʤ�ʤ��¤ꡢ��������ʤ������ξ��Ǥ� $DATA �ϲ�������ʤ��� + + @return + ��������������С�mtext_from_data () �ϳ�����Ƥ�줿M-text + �ؤΥݥ��󥿤��֤��������Ǥʤ���� @c NULL ���֤������ѿ� #merror_code + �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_MTEXT */ + +MText * +mtext_from_data (const void *data, int nitems, enum MTextFormat format) +{ + if (nitems < 0 + || format < MTEXT_FORMAT_US_ASCII || format >= MTEXT_FORMAT_MAX) + MERROR (MERROR_MTEXT, NULL); + return mtext__from_data (data, nitems, format, 0); +} + +/*=*/ + +/***en + @brief Get information about the text data in M-text. + + The mtext_data () function returns a pointer to the text data of + M-text $MT. If $FMT is not NULL, the format of the text data is + stored in it. If $NUNITS is not NULL, the number of units of the + text data is stored in it. + + If $POS_IDX is not NULL and it points to a non-negative number, + what it points to is a character position. In this case, the + return value is a pointer to the text data of a character at that + position. + + Otherwise, if $UNIT_IDX is not NULL, it points to a unit position. + In this case, the return value is a pointer to the text data of a + character containing that unit. + + The character position and unit position of the return value are + stored in $POS_IDX and $UNIT_DIX respectively if they are not + NULL. + +
    + +
  • If the format of the text data is MTEXT_FORMAT_US_ASCII or + MTEXT_FORMAT_UTF_8, one unit is unsigned char. + +
  • If the format is MTEXT_FORMAT_UTF_16LE or + MTEXT_FORMAT_UTF_16BE, one unit is unsigned short. + +
  • If the format is MTEXT_FORMAT_UTF_32LE or + MTEXT_FORMAT_UTF_32BE, one unit is unsigned int. + +
*/ + +void * +mtext_data (MText *mt, enum MTextFormat *fmt, int *nunits, + int *pos_idx, int *unit_idx) +{ + void *data; + int pos = 0, unit_pos = 0; + + if (fmt) + *fmt = mt->format; + data = MTEXT_DATA (mt); + if (pos_idx && *pos_idx >= 0) + { + pos = *pos_idx; + if (pos > mtext_nchars (mt)) + MERROR (MERROR_MTEXT, NULL); + unit_pos = POS_CHAR_TO_BYTE (mt, pos); + } + else if (unit_idx) + { + unit_pos = *unit_idx; + + if (unit_pos < 0 || unit_pos > mtext_nbytes (mt)) + MERROR (MERROR_MTEXT, NULL); + pos = POS_BYTE_TO_CHAR (mt, unit_pos); + unit_pos = POS_CHAR_TO_BYTE (mt, pos); + } + if (nunits) + *nunits = mtext_nbytes (mt) - unit_pos; + if (pos_idx) + *pos_idx = pos; + if (unit_idx) + *unit_idx = unit_pos; + if (unit_pos > 0) + { + if (mt->format <= MTEXT_FORMAT_UTF_8) + data = (unsigned char *) data + unit_pos; + else if (mt->format <= MTEXT_FORMAT_UTF_16BE) + data = (unsigned short *) data + unit_pos; + else + data = (unsigned int *) data + unit_pos; + } + return data; +} + +/*=*/ + +/***en + @brief Number of characters in M-text. + + The mtext_len () function returns the number of characters in + M-text $MT. */ + +/***ja + @brief M-text ���ʸ���ο�. + + �ؿ� mtext_len () �� M-text $MT ���ʸ���ο����֤��� + + @latexonly \IPAlabel{mtext_len} @endlatexonly */ + +int +mtext_len (MText *mt) +{ + return (mt->nchars); +} + +/*=*/ + +/***en + @brief Return the character at the specified position in an M-text. + + The mtext_ref_char () function returns the character at $POS in + M-text $MT. If an error is detected, it returns -1 and assigns an + error code to the external variable #merror_code. */ + +/***ja + @brief M-text ��λ��ꤵ�줿���֤�ʸ�����֤�. + + �ؿ� mtext_ref_char () �ϡ�M-text $MT �ΰ��� $POS + ��ʸ�����֤������顼�����Ф��줿���� -1 ���֤��������ѿ� #merror_code + �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mtext_ref_char} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE */ + +int +mtext_ref_char (MText *mt, int pos) +{ + int c; + + M_CHECK_POS (mt, pos, -1); + if (mt->format <= MTEXT_FORMAT_UTF_8) + { + unsigned char *p = mt->data + POS_CHAR_TO_BYTE (mt, pos); + + c = STRING_CHAR_UTF8 (p); + } + else if (mt->format <= MTEXT_FORMAT_UTF_16BE) + { + unsigned short *p + = (unsigned short *) (mt->data) + POS_CHAR_TO_BYTE (mt, pos); + unsigned short p1[2]; + + if (mt->format != MTEXT_FORMAT_UTF_16) + { + p1[0] = SWAP_16 (*p); + if (p1[0] >= 0xD800 && p1[0] < 0xDC00) + p1[1] = SWAP_16 (p[1]); + p = p1; + } + c = STRING_CHAR_UTF16 (p); + } + else + { + c = ((unsigned *) (mt->data))[pos]; + if (mt->format != MTEXT_FORMAT_UTF_32) + c = SWAP_32 (c); + } + return c; +} + +/*=*/ + +/***en + @brief Store a character into an M-text. + + The mtext_set_char () function sets character $C, which has no + text properties, at $POS in M-text $MT. + + @return + If the operation was successful, mtext_set_char () returns 0. + Otherwise it returns -1 and assigns an error code to the external + variable #merror_code. */ + +/***ja + @brief M-text �˰�ʸ�������ꤹ��. + + �ؿ� mtext_set_char () �ϡ��ƥ����ȥץ��ѥƥ�̵����ʸ�� $C �� + M-text $MT �ΰ��� $POS �����ꤹ�롣 + + @return + ��������������� mtext_set_char () �� 0 ���֤������Ԥ���� -1 + ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mtext_set_char} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE */ + +int +mtext_set_char (MText *mt, int pos, int c) +{ + int pos_unit; + int old_units, new_units; + int delta; + unsigned char *p; + int unit_bytes; + + M_CHECK_POS (mt, pos, -1); + M_CHECK_READONLY (mt, -1); + + mtext__adjust_plist_for_change (mt, pos, 1, 1); + + if (mt->format <= MTEXT_FORMAT_UTF_8) + { + if (c >= 0x80) + mt->format = MTEXT_FORMAT_UTF_8, mt->coverage = MTEXT_COVERAGE_FULL; + } + else if (mt->format <= MTEXT_FORMAT_UTF_16BE) + { + if (c >= 0x110000) + mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8); + else if (mt->format != MTEXT_FORMAT_UTF_16) + mtext__adjust_format (mt, MTEXT_FORMAT_UTF_16); + } + else if (mt->format != MTEXT_FORMAT_UTF_32) + mtext__adjust_format (mt, MTEXT_FORMAT_UTF_32); + + unit_bytes = UNIT_BYTES (mt->format); + pos_unit = POS_CHAR_TO_BYTE (mt, pos); + p = mt->data + pos_unit * unit_bytes; + old_units = CHAR_UNITS_AT (mt, p); + new_units = CHAR_UNITS (c, mt->format); + delta = new_units - old_units; + + if (delta) + { + if (mt->cache_char_pos > pos) + mt->cache_byte_pos += delta; + + if ((mt->nbytes + delta + 1) * unit_bytes > mt->allocated) + { + mt->allocated = (mt->nbytes + delta + 1) * unit_bytes; + MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT); + } + + memmove (mt->data + (pos_unit + new_units) * unit_bytes, + mt->data + (pos_unit + old_units) * unit_bytes, + (mt->nbytes - pos_unit - old_units + 1) * unit_bytes); + mt->nbytes += delta; + mt->data[mt->nbytes * unit_bytes] = 0; + } + switch (mt->format) + { + case MTEXT_FORMAT_US_ASCII: + mt->data[pos_unit] = c; + break; + case MTEXT_FORMAT_UTF_8: + { + unsigned char *p = mt->data + pos_unit; + CHAR_STRING_UTF8 (c, p); + break; + } + default: + if (mt->format == MTEXT_FORMAT_UTF_16) + { + unsigned short *p = (unsigned short *) mt->data + pos_unit; + + CHAR_STRING_UTF16 (c, p); + } + else + ((unsigned *) mt->data)[pos_unit] = c; + } + return 0; +} + +/*=*/ + +/***en + @brief Append a character to an M-text. + + The mtext_cat_char () function appends character $C, which has no + text properties, to the end of M-text $MT. + + @return + This function returns a pointer to the resulting M-text $MT. If + $C is an invalid character, it returns @c NULL. */ + +/***ja + @brief M-text �˰�ʸ���ɲä���. + + �ؿ� mtext_cat_char () �ϡ��ƥ����ȥץ��ѥƥ�̵����ʸ�� $C �� + M-text $MT ���������ɲä��롣 + + @return + ���δؿ����ѹ����줿 M-text $MT �ؤΥݥ��󥿤��֤���$C + ��������ʸ���Ǥʤ����ˤ� @c NULL ���֤��� */ + +/*** + @seealso + mtext_cat (), mtext_ncat () */ + +MText * +mtext_cat_char (MText *mt, int c) +{ + int nunits; + int unit_bytes = UNIT_BYTES (mt->format); + + M_CHECK_READONLY (mt, NULL); + if (c < 0 || c > MCHAR_MAX) + return NULL; + mtext__adjust_plist_for_insert (mt, mt->nchars, 1, NULL); + + if (c >= 0x80 + && (mt->format == MTEXT_FORMAT_US_ASCII + || (c >= 0x10000 + && (mt->format == MTEXT_FORMAT_UTF_16LE + || mt->format == MTEXT_FORMAT_UTF_16BE)))) + + { + mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8); + unit_bytes = 1; + } + else if (mt->format >= MTEXT_FORMAT_UTF_32LE) + { + if (mt->format != MTEXT_FORMAT_UTF_32) + mtext__adjust_format (mt, MTEXT_FORMAT_UTF_32); + } + else if (mt->format >= MTEXT_FORMAT_UTF_16LE) + { + if (mt->format != MTEXT_FORMAT_UTF_16) + mtext__adjust_format (mt, MTEXT_FORMAT_UTF_16); + } + + nunits = CHAR_UNITS (c, mt->format); + if ((mt->nbytes + nunits + 1) * unit_bytes > mt->allocated) + { + mt->allocated = (mt->nbytes + nunits * 16 + 1) * unit_bytes; + MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT); + } + + if (mt->format <= MTEXT_FORMAT_UTF_8) + { + unsigned char *p = mt->data + mt->nbytes; + p += CHAR_STRING_UTF8 (c, p); + *p = 0; + } + else if (mt->format == MTEXT_FORMAT_UTF_16) + { + unsigned short *p = (unsigned short *) mt->data + mt->nbytes; + p += CHAR_STRING_UTF16 (c, p); + *p = 0; + } + else + { + unsigned *p = (unsigned *) mt->data + mt->nbytes; + *p++ = c; + *p = 0; + } + + mt->nchars++; + mt->nbytes += nunits; + return mt; +} + +/*=*/ + +/***en + @brief Create a copy of an M-text. + + The mtext_dup () function creates a copy of M-text $MT while + inheriting all the text properties of $MT. + + @return + This function returns a pointer to the created copy. */ + +/***ja + @brief M-text �Υ��ԡ�����. + + �ؿ� mtext_dup () �ϡ�M-text $MT �Υ��ԡ����롣$MT + �Υƥ����ȥץ��ѥƥ��Ϥ��٤ƷѾ�����롣 + + @return + ���δؿ��Ϻ��줿���ԡ��ؤΥݥ��󥿤��֤��� + + @latexonly \IPAlabel{mtext_dup} @endlatexonly */ + +/*** + @seealso + mtext_duplicate () */ + +MText * +mtext_dup (MText *mt) +{ + return mtext_duplicate (mt, 0, mtext_nchars (mt)); +} + +/*=*/ + +/***en + @brief Append an M-text to another. + + The mtext_cat () function appends M-text $MT2 to the end of M-text + $MT1 while inheriting all the text properties. $MT2 itself is not + modified. + + @return + This function returns a pointer to the resulting M-text $MT1. */ + +/***ja + @brief 2�Ĥ� M-text��Ϣ�뤹��. + + �ؿ� mtext_cat () �ϡ� M-text $MT2 �� M-text $MT1 + ���������դ��ä��롣$MT2 �Υƥ����ȥץ��ѥƥ��Ϥ��٤ƷѾ�����롣$MT2 ���ѹ�����ʤ��� + + @return + ���δؿ����ѹ����줿 M-text $MT1 �ؤΥݥ��󥿤��֤��� + + @latexonly \IPAlabel{mtext_cat} @endlatexonly */ + +/*** + @seealso + mtext_ncat (), mtext_cat_char () */ + +MText * +mtext_cat (MText *mt1, MText *mt2) +{ + M_CHECK_READONLY (mt1, NULL); + + if (mt2->nchars > 0) + insert (mt1, mt1->nchars, mt2, 0, mt2->nchars); + return mt1; +} + + +/*=*/ + +/***en + @brief Append a part of an M-text to another. + + The mtext_ncat () function appends the first $N characters of + M-text $MT2 to the end of M-text $MT1 while inheriting all the + text properties. If the length of $MT2 is less than $N, all + characters are copied. $MT2 is not modified. + + @return + If the operation was successful, mtext_ncat () returns a + pointer to the resulting M-text $MT1. If an error is detected, it + returns @c NULL and assigns an error code to the global variable + #merror_code. */ + +/***ja + @brief M-text �ΰ������̤� M-text ���ղä���. + + �ؿ� mtext_ncat () �ϡ�M-text $MT2 �ΤϤ���� $N ʸ���� M-text + $MT1 ���������դ��ä��롣$MT2 �Υƥ����ȥץ��ѥƥ��Ϥ��٤ƷѾ�����롣$MT2 + ��Ĺ���� $N �ʲ��ʤ�С�$MT2 �Τ��٤Ƥ�ʸ�����ղä���롣 $MT2 ���ѹ�����ʤ��� + + @return + ����������������硢mtext_ncat () ���ѹ����줿 M-text $MT1 + �ؤΥݥ��󥿤��֤������顼�����Ф��줿���� @c NULL ���֤��������ѿ� + #merror_code �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mtext_ncat} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE + + @seealso + mtext_cat (), mtext_cat_char () */ + +MText * +mtext_ncat (MText *mt1, MText *mt2, int n) +{ + M_CHECK_READONLY (mt1, NULL); + if (n < 0) + MERROR (MERROR_RANGE, NULL); + if (mt2->nchars > 0) + insert (mt1, mt1->nchars, mt2, 0, mt2->nchars < n ? mt2->nchars : n); + return mt1; +} + + +/*=*/ + +/***en + @brief Copy an M-text to another. + + The mtext_cpy () function copies M-text $MT2 to M-text $MT1 while + inheriting all the text properties. The old text in $MT1 is + overwritten and the length of $MT1 is extended if necessary. $MT2 + is not modified. + + @return + This function returns a pointer to the resulting M-text $MT1. */ + +/***ja + @brief M-text ���̤� M-text �˥��ԡ�����. + + �ؿ� mtext_cpy () �� M-text $MT2 �� M-text $MT1 �˾�񤭥��ԡ����롣 + $MT2 �Υƥ����ȥץ��ѥƥ��Ϥ��٤ƷѾ�����롣$MT1 + ��Ĺ����ɬ�פ˱����ƿ��Ф���롣$MT2 ���ѹ�����ʤ��� + + @return + ���δؿ����ѹ����줿 M-text $MT1 �ؤΥݥ��󥿤��֤��� + + @latexonly \IPAlabel{mtext_cpy} @endlatexonly */ + +/*** + @seealso + mtext_ncpy (), mtext_copy () */ + +MText * +mtext_cpy (MText *mt1, MText *mt2) +{ + M_CHECK_READONLY (mt1, NULL); + mtext_del (mt1, 0, mt1->nchars); + if (mt2->nchars > 0) + insert (mt1, 0, mt2, 0, mt2->nchars); + return mt1; +} + +/*=*/ + +/***en + @brief Copy the first some characters in an M-text to another. + + The mtext_ncpy () function copies the first $N characters of + M-text $MT2 to M-text $MT1 while inheriting all the text + properties. If the length of $MT2 is less than $N, all characters + of $MT2 are copied. The old text in $MT1 is overwritten and the + length of $MT1 is extended if necessary. $MT2 is not modified. + + @return + If the operation was successful, mtext_ncpy () returns a pointer + to the resulting M-text $MT1. If an error is detected, it returns + @c NULL and assigns an error code to the global variable + #merror_code. */ + +/***ja + @brief M-text �˴ޤޤ��ǽ�β�ʸ�����򥳥ԡ�����. + + �ؿ� mtext_ncpy () �ϡ�M-text $MT2 �κǽ�� $N ʸ���� M-text $MT1 + �˾�񤭥��ԡ����롣$MT2 �Υƥ����ȥץ��ѥƥ��Ϥ��٤ƷѾ�����롣�⤷ $MT2 + ��Ĺ���� $N ���⾮������� $MT2 �Τ��٤Ƥ�ʸ���򥳥ԡ����롣$MT1 + ��Ĺ����ɬ�פ˱����ƿ��Ф���롣$MT2 ���ѹ�����ʤ��� + + @return + ����������������硢mtext_ncpy () ���ѹ����줿 M-text $MT1 + �ؤΥݥ��󥿤��֤������顼�����Ф��줿���� @c NULL ���֤��������ѿ� + #merror_code �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mtext_ncpy} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE + + @seealso + mtext_cpy (), mtext_copy () */ + +MText * +mtext_ncpy (MText *mt1, MText *mt2, int n) +{ + M_CHECK_READONLY (mt1, NULL); + if (n < 0) + MERROR (MERROR_RANGE, NULL); + mtext_del (mt1, 0, mt1->nchars); + if (mt2->nchars > 0) + insert (mt1, 0, mt2, 0, mt2->nchars < n ? mt2->nchars : n); + return mt1; +} + +/*=*/ + +/***en + @brief Create a new M-text from a part of an existing M-text. + + The mtext_duplicate () function creates a copy of sub-text of + M-text $MT, starting at $FROM (inclusive) and ending at $TO + (exclusive) while inheriting all the text properties of $MT. $MT + itself is not modified. + + @return + If the operation was successful, mtext_duplicate () + returns a pointer to the created M-text. If an error is detected, + it returns NULL and assigns an error code to the external variable + #merror_code. */ + +/***ja + @brief ��¸�� M-text �ΰ������鿷���� M-text ��Ĥ���. + + �ؿ� mtext_duplicate () �ϡ�M-text $MT �� $FROM ��$FROM ���Τ�ޤ�ˤ��� + $TO ��$TO ���Τϴޤޤʤ��ˤޤǤ���ʬ�Υ��ԡ����롣���ΤȤ� $MT + �Υƥ����ȥץ��ѥƥ��Ϥ��٤ƷѾ�����롣$MT ���Τ�Τ��ѹ�����ʤ��� + + @return + ��������������С�mtext_duplicate () �Ϻ��줿 M-text + �ؤΥݥ��󥿤��֤������顼�����Ф��줿���� @c NULL ���֤��������ѿ� + #merror_code �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mtext_duplicate} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE + + @seealso + mtext_dup () */ + +MText * +mtext_duplicate (MText *mt, int from, int to) +{ + MText *new = mtext (); + + M_CHECK_RANGE (mt, from, to, NULL, new); + new->format = mt->format; + new->coverage = mt->coverage; + insert (new, 0, mt, from, to); + return new; +} + +/*=*/ + +/***en + @brief Copy characters in the specified range into an M-text. + + The mtext_copy () function copies the text between $FROM + (inclusive) and $TO (exclusive) in M-text $MT2 to the region + starting at $POS in M-text $MT1 while inheriting the text + properties. The old text in $MT1 is overwritten and the length of + $MT1 is extended if necessary. $MT2 is not modified. + + @return + If the operation was successful, mtext_copy () returns a pointer + to the modified $MT1. Otherwise, it returns @c NULL and assigns + an error code to the external variable #merror_code. */ + +/***ja + @brief M-text �˻����ϰϤ�ʸ���򥳥ԡ�����. + + �ؿ� mtext_copy () �ϡ� M-text $MT2 �� $FROM ��$FROM ���Τ�ޤ�ˤ��� + $TO ��$TO ���Τϴޤޤʤ��ˤޤǤ��ϰϤΥƥ����Ȥ� M-text $MT1 �ΰ��� $POS + �����񤭥��ԡ����롣$MT2 �Υƥ����ȥץ��ѥƥ��Ϥ��٤ƷѾ�����롣$MT1 + ��Ĺ����ɬ�פ˱����ƿ��Ф���롣$MT2 ���ѹ�����ʤ��� + + @latexonly \IPAlabel{mtext_copy} @endlatexonly + + @return + ����������������硢mtext_copy () ���ѹ����줿 $MT1 + �ؤΥݥ��󥿤��֤��������Ǥʤ���� @c NULL ���֤��������ѿ� #merror_code + �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_RANGE + + @seealso + mtext_cpy (), mtext_ncpy () */ + +MText * +mtext_copy (MText *mt1, int pos, MText *mt2, int from, int to) +{ + M_CHECK_POS_X (mt1, pos, NULL); + M_CHECK_READONLY (mt1, NULL); + M_CHECK_RANGE_X (mt2, from, to, NULL); + mtext_del (mt1, pos, mt1->nchars); + return insert (mt1, pos, mt2, from, to); +} + +/*=*/ + + +/***en + @brief Delete characters in the specified range destructively. + + The mtext_del () function deletes the characters in the range + $FROM (inclusive) and $TO (exclusive) from M-text $MT + destructively. As a result, the length of $MT shrinks by ($TO - + $FROM) characters. + + @return + If the operation was successful, mtext_del () returns 0. + Otherwise, it returns -1 and assigns an error code to the external + variable #merror_code. */ + +/***ja + @brief �����ϰϤ�ʸ�����˲�Ū�˼�����. + + �ؿ� mtext_del () �ϡ�M-text $MT �� $FROM ��$FROM ���Τ�ޤ�ˤ��� + $TO ��$TO ���Τϴޤޤʤ��ˤޤǤ�ʸ�����˲�Ū�˼����������Ū�� + $MT ��Ĺ���� ($TO @c - $FROM) �����̤ळ�Ȥˤʤ롣 + + @return + ��������������� mtext_del () �� 0 ���֤��������Ǥʤ���� -1 + ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_RANGE + + @seealso + mtext_ins () */ + +int +mtext_del (MText *mt, int from, int to) +{ + int from_byte, to_byte; + int unit_bytes = UNIT_BYTES (mt->format); + + M_CHECK_READONLY (mt, -1); + M_CHECK_RANGE (mt, from, to, -1, 0); + + from_byte = POS_CHAR_TO_BYTE (mt, from); + to_byte = POS_CHAR_TO_BYTE (mt, to); + + if (mt->cache_char_pos >= to) + { + mt->cache_char_pos -= to - from; + mt->cache_byte_pos -= to_byte - from_byte; + } + else if (mt->cache_char_pos > from) + { + mt->cache_char_pos -= from; + mt->cache_byte_pos -= from_byte; + } + + mtext__adjust_plist_for_delete (mt, from, to - from); + memmove (mt->data + from_byte * unit_bytes, + mt->data + to_byte * unit_bytes, + (mt->nbytes - to_byte + 1) * unit_bytes); + mt->nchars -= (to - from); + mt->nbytes -= (to_byte - from_byte); + mt->cache_char_pos = from; + mt->cache_byte_pos = from_byte; + return 0; +} + + +/*=*/ + +/***en + @brief Insert an M-text into another M-text. + + The mtext_ins () function inserts M-text $MT2 into M-text $MT1, at + position $POS. As a result, $MT1 is lengthen by the length of + $MT2. On insertion, all the text properties of $MT2 are + inherited. The original $MT2 is not modified. + + @return + If the operation was successful, mtext_ins () returns 0. + Otherwise, it returns -1 and assigns an error code to the external + variable #merror_code. */ + +/***ja + @brief M-text ���̤� M-text ����������. + + �ؿ� mtext_ins () �� M-text $MT1 �� $POS �ΰ��֤��̤� M-text $MT2 + ���������롣���η�� $MT1 ��Ĺ���� $MT2 ��Ĺ��ʬ���������롣�����κݡ�$MT2 + �Υƥ����ȥץ��ѥƥ��Ϥ��٤ƷѾ�����롣$MT2 ���Τ�Τ��ѹ�����ʤ��� + + @return + ��������������� mtext_ins () �� 0 ���֤��������Ǥʤ���� -1 + ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_RANGE , @c MERROR_MTEXT + + @seealso + mtext_del () , mtext_insert () */ + +int +mtext_ins (MText *mt1, int pos, MText *mt2) +{ + M_CHECK_READONLY (mt1, -1); + M_CHECK_POS_X (mt1, pos, -1); + + if (mt2->nchars == 0) + return 0; + insert (mt1, pos, mt2, 0, mt2->nchars); + return 0; +} + +/*=*/ + +/***en + @brief Insert sub-text of an M-text into another M-text. + + The mtext_insert () function inserts sub-text of M-text $MT2 + between $FROM (inclusive) and $TO (exclusive) into M-text $MT1, at + position $POS. As a result, $MT1 is lengthen by ($TO - $FROM). + On insertion, all the text properties of the sub-text of $MT2 are + inherited. + + @return + If the operation was successful, mtext_insert () returns + 0. Otherwise, it returns -1 and assigns an error code to the + external variable #merror_code. */ + +/***ja + @brief M-text �ΰ������̤� M-text ����������. + + �ؿ� mtext_insert () �� M-text $MT1 ��� $POS �ΰ��֤ˡ��̤� + M-text $MT2 �� $FROM ��$FROM ���Τ�ޤ�ˤ��� $TO ��$TO ���Τϴޤ� + �ʤ��ˤޤǤ�ʸ�����������롣���Ū�� $MT1 ��Ĺ���� ($TO - $FROM) + �������Ӥ롣�����κݡ� $MT2 ��Υƥ����ȥץ��ѥƥ��Ϥ��٤ƷѾ����� + �롣 + + @return + ��������������С�mtext_insert () �� 0 ���֤��������Ǥʤ���� -1 + ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_MTEXT , @c MERROR_RANGE + + @seealso + mtext_ins () */ + +int +mtext_insert (MText *mt1, int pos, MText *mt2, int from, int to) +{ + M_CHECK_READONLY (mt1, -1); + M_CHECK_POS_X (mt1, pos, -1); + M_CHECK_RANGE (mt2, from, to, -1, 0); + + insert (mt1, pos, mt2, from, to); + return 0; +} + +/*=*/ + +/***en + @brief Insert a character into an M-text. + + The mtext_ins_char () function inserts $N copies of character $C + into M-text $MT at position $POS. As a result, $MT is lengthen by + $N. + + @return + If the operation was successful, mtext_ins () returns 0. + Otherwise, it returns -1 and assigns an error code to the external + variable #merror_code. */ + +/***ja + @brief M-text ��ʸ������������. + + �ؿ� mtext_ins_char () �� M-text $MT �� $POS �ΰ��֤�ʸ�� $C �Υ��ԡ��� $N + ���������롣���η�� $MT1 ��Ĺ���� $N ���������롣 + + @return + ��������������� mtext_ins_char () �� 0 ���֤��������Ǥʤ���� -1 + ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_RANGE + + @seealso + mtext_ins, mtext_del () */ + +int +mtext_ins_char (MText *mt, int pos, int c, int n) +{ + int nunits; + int unit_bytes = UNIT_BYTES (mt->format); + int pos_unit; + int i; + + M_CHECK_READONLY (mt, -1); + M_CHECK_POS_X (mt, pos, -1); + if (c < 0 || c > MCHAR_MAX) + MERROR (MERROR_MTEXT, -1); + if (n <= 0) + return 0; + mtext__adjust_plist_for_insert (mt, pos, n, NULL); + + if (c >= 0x80 + && (mt->format == MTEXT_FORMAT_US_ASCII + || (c >= 0x10000 && (mt->format == MTEXT_FORMAT_UTF_16LE + || mt->format == MTEXT_FORMAT_UTF_16BE)))) + { + mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8); + unit_bytes = 1; + } + else if (mt->format >= MTEXT_FORMAT_UTF_32LE) + { + if (mt->format != MTEXT_FORMAT_UTF_32) + mtext__adjust_format (mt, MTEXT_FORMAT_UTF_32); + } + else if (mt->format >= MTEXT_FORMAT_UTF_16LE) + { + if (mt->format != MTEXT_FORMAT_UTF_16) + mtext__adjust_format (mt, MTEXT_FORMAT_UTF_16); + } + + nunits = CHAR_UNITS (c, mt->format); + if ((mt->nbytes + nunits * n + 1) * unit_bytes > mt->allocated) + { + mt->allocated = (mt->nbytes + nunits * n + 1) * unit_bytes; + MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT); + } + pos_unit = POS_CHAR_TO_BYTE (mt, pos); + if (mt->cache_char_pos > pos) + { + mt->cache_char_pos += n; + mt->cache_byte_pos += nunits * n; + } + memmove (mt->data + (pos_unit + nunits * n) * unit_bytes, + mt->data + pos_unit * unit_bytes, + (mt->nbytes - pos_unit + 1) * unit_bytes); + if (mt->format <= MTEXT_FORMAT_UTF_8) + { + unsigned char *p = mt->data + pos_unit; + + for (i = 0; i < n; i++) + p += CHAR_STRING_UTF8 (c, p); + } + else if (mt->format == MTEXT_FORMAT_UTF_16) + { + unsigned short *p = (unsigned short *) mt->data + pos_unit; + + for (i = 0; i < n; i++) + p += CHAR_STRING_UTF16 (c, p); + } + else + { + unsigned *p = (unsigned *) mt->data + pos_unit; + + for (i = 0; i < n; i++) + *p++ = c; + } + mt->nchars += n; + mt->nbytes += nunits * n; + return 0; +} + +/*=*/ + +/***en + @brief Replace sub-text of M-text with another. + + The mtext_replace () function replaces sub-text of M-text $MT1 + between $FROM1 (inclusive) and $TO1 (exclusive) with the sub-text + of M-text $MT2 between $FROM2 (inclusive) and $TO2 (exclusive). + The new sub-text inherits text properties of the old sub-text. + + @return + If the operation was successful, mtext_replace () returns + 0. Otherwise, it returns -1 and assigns an error code to the + external variable #merror_code. */ + +/***ja + @brief M-text �ΰ������̤� M-text �ΰ������ִ�����. + + �ؿ� mtext_replace () �ϡ� M-text $MT1 �� $FROM1 ��$FROM1 ���Τ�� + ��ˤ��� $TO1 ��$TO1 ���Τϴޤޤʤ��ˤޤǤ� M-text $MT2 �� + $FROM2 ��$FROM2 ���Τ�ޤ�ˤ��� $TO2 ��$TO2 ���Τϴޤޤʤ��ˤ��� + �������롣�������������줿��ʬ�ϡ��֤����������Υƥ����ȥץ��ѥƥ� + ���٤Ƥ�Ѿ����롣 + + @return + ��������������С� mtext_replace () �� 0 ���֤��������Ǥ� + ����� -1 ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_MTEXT , @c MERROR_RANGE + + @seealso + mtext_insert () */ + +int +mtext_replace (MText *mt1, int from1, int to1, + MText *mt2, int from2, int to2) +{ + int len1, len2; + int from1_byte, from2_byte, old_bytes, new_bytes; + int unit_bytes, total_bytes; + unsigned char *p; + int free_mt2 = 0; + + M_CHECK_READONLY (mt1, -1); + M_CHECK_RANGE_X (mt1, from1, to1, -1); + M_CHECK_RANGE_X (mt2, from2, to2, -1); + + if (from1 == to1) + { + struct MTextPlist *saved = mt2->plist; + + mt2->plist = NULL; + insert (mt1, from1, mt2, from2, to2); + mt2->plist = saved; + return 0; + } + + if (from2 == to2) + { + return mtext_del (mt1, from1, to1); + } + + if (mt1 == mt2) + { + mt2 = mtext_duplicate (mt2, from2, to2); + to2 -= from2; + from2 = 0; + free_mt2 = 1; + } + + if (mt1->format != mt2->format + && mt1->format == MTEXT_FORMAT_US_ASCII) + mt1->format = MTEXT_FORMAT_UTF_8; + if (mt1->format != mt2->format + && mt1->coverage < mt2->coverage) + mtext__adjust_format (mt1, mt2->format); + if (mt1->format != mt2->format) + { + mt2 = mtext_duplicate (mt2, from2, to2); + mtext__adjust_format (mt2, mt1->format); + to2 -= from2; + from2 = 0; + free_mt2 = 1; + } + + len1 = to1 - from1; + len2 = to2 - from2; + mtext__adjust_plist_for_change (mt1, from1, len1, len2); + + unit_bytes = UNIT_BYTES (mt1->format); + from1_byte = POS_CHAR_TO_BYTE (mt1, from1) * unit_bytes; + from2_byte = POS_CHAR_TO_BYTE (mt2, from2) * unit_bytes; + old_bytes = POS_CHAR_TO_BYTE (mt1, to1) * unit_bytes - from1_byte; + new_bytes = POS_CHAR_TO_BYTE (mt2, to2) * unit_bytes - from2_byte; + total_bytes = mt1->nbytes * unit_bytes + (new_bytes - old_bytes); + if (total_bytes + unit_bytes > mt1->allocated) + { + mt1->allocated = total_bytes + unit_bytes; + MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT); + } + p = mt1->data + from1_byte; + if (to1 < mt1->nchars + && old_bytes != new_bytes) + memmove (p + new_bytes, p + old_bytes, + (mt1->nbytes + 1) * unit_bytes - (from1_byte + old_bytes)); + memcpy (p, mt2->data + from2_byte, new_bytes); + mt1->nchars += len2 - len1; + mt1->nbytes += (new_bytes - old_bytes) / unit_bytes; + if (mt1->cache_char_pos >= to1) + { + mt1->cache_char_pos += len2 - len1; + mt1->cache_byte_pos += new_bytes - old_bytes; + } + else if (mt1->cache_char_pos > from1) + { + mt1->cache_char_pos = from1; + mt1->cache_byte_pos = from1_byte; + } + + if (free_mt2) + M17N_OBJECT_UNREF (mt2); + return 0; +} + +/*=*/ + +/***en + @brief Search a character in an M-text. + + The mtext_character () function searches M-text $MT for character + $C. If $FROM is less than $TO, the search begins at position $FROM + and goes forward but does not exceed ($TO - 1). Otherwise, the search + begins at position ($FROM - 1) and goes backward but does not + exceed $TO. An invalid position specification is regarded as both + $FROM and $TO being 0. + + @return + If $C is found, mtext_character () returns the position of its + first occurrence. Otherwise it returns -1 without changing the + external variable #merror_code. If an error is detected, it returns -1 and + assigns an error code to the external variable #merror_code. */ + +/***ja + @brief M-text ���ʸ����õ��. + + �ؿ� mtext_character () �� M-text $MT ���ʸ�� $C ��õ�����⤷ + $FROM �� $TO ��꾮������С�õ���ϰ��� $FROM �������������ء����� + ($TO - 1) �ޤǿʤࡣ�����Ǥʤ���а��� ($FROM - 1) ������Ƭ�����ء����� + $TO �ޤǿʤࡣ���֤λ���˸��꤬������ϡ�$FROM �� $TO + ��ξ���� 0 �����ꤵ�줿��ΤȤߤʤ��� + + @return + �⤷ $C �����Ĥ���С�mtext_character () + �Ϥ��κǽ�νи����֤��֤������Ĥ���ʤ��ä����ϳ����ѿ� #merror_code + ���ѹ������� -1 ���֤������顼�����Ф��줿���� -1 ���֤��������ѿ� + #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @seealso + mtext_chr(), mtext_rchr () */ + +int +mtext_character (MText *mt, int from, int to, int c) +{ + if (from < to) + { + /* We do not use M_CHECK_RANGE () because this function should + not set merror_code. */ + if (from < 0 || to > mt->nchars) + return -1; + return find_char_forward (mt, from, to, c); + } + else + { + /* ditto */ + if (to < 0 || from > mt->nchars) + return -1; + return find_char_backward (mt, to, from, c); + } +} + + +/*=*/ + +/***en + @brief Return the position of the first occurrence of a character in an M-text. + + The mtext_chr () function searches M-text $MT for character $C. + The search starts from the beginning of $MT and goes toward the end. + + @return + If $C is found, mtext_chr () returns its position; otherwise it + returns -1. */ + +/***ja + @brief M-text ��ǻ��ꤵ�줿ʸ�����ǽ�˸������֤��֤�. + + �ؿ� mtext_chr () �� M-text $MT ���ʸ�� $C ��õ����õ���� $MT + ����Ƭ�������������˿ʤࡣ + + @return + �⤷ $C �����Ĥ���С�mtext_chr () + �Ϥ��νи����֤��֤������Ĥ���ʤ��ä����� -1 ���֤��� + + @latexonly \IPAlabel{mtext_chr} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE + + @seealso + mtext_rchr (), mtext_character () */ + +int +mtext_chr (MText *mt, int c) +{ + return find_char_forward (mt, 0, mt->nchars, c); +} + +/*=*/ + +/***en + @brief Return the position of the last occurrence of a character in an M-text. + + The mtext_rchr () function searches M-text $MT for character $C. + The search starts from the end of $MT and goes backwardly toward the + beginning. + + @return + If $C is found, mtext_rchr () returns its position; otherwise it + returns -1. */ + +/***ja + @brief M-text ��ǻ��ꤵ�줿ʸ�����Ǹ�˸������֤��֤�. + + �ؿ� mtext_rchr () �� M-text $MT ���ʸ�� $C ��õ����õ���� $MT + �κǸ夫����Ƭ�����ؤȸ�����˿ʤࡣ + + @return + �⤷ $C �����Ĥ���С�mtext_rchr () + �Ϥ��νи����֤��֤������Ĥ���ʤ��ä����� -1 ���֤��� + + @latexonly \IPAlabel{mtext_rchr} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE + + @seealso + mtext_chr (), mtext_character () */ + +int +mtext_rchr (MText *mt, int c) +{ + return find_char_backward (mt, mt->nchars, 0, c); +} + + +/*=*/ + +/***en + @brief Compare two M-texts character-by-character. + + The mtext_cmp () function compares M-texts $MT1 and $MT2 character + by character. + + @return + This function returns 1, 0, or -1 if $MT1 is found greater than, + equal to, or less than $MT2, respectively. Comparison is based on + character codes. */ + +/***ja + @brief ��Ĥ� M-text ��ʸ��ñ�̤���Ӥ���. + + �ؿ� mtext_cmp () �ϡ� M-text $MT1 �� $MT2 ��ʸ��ñ�̤���Ӥ��롣 + + @return + ���δؿ��ϡ�$MT1 �� $MT2 ����������� 0��$MT1 �� $MT2 ����礭����� + 1��$MT1 �� $MT2 ��꾮������� -1 ���֤�����Ӥ�ʸ�������ɤ˴�Ť��� + + @latexonly \IPAlabel{mtext_cmp} @endlatexonly */ + +/*** + @seealso + mtext_ncmp (), mtext_casecmp (), mtext_ncasecmp (), + mtext_compare (), mtext_case_compare () */ + +int +mtext_cmp (MText *mt1, MText *mt2) +{ + return compare (mt1, 0, mt1->nchars, mt2, 0, mt2->nchars); +} + + +/*=*/ + +/***en + @brief Compare initial parts of two M-texts character-by-character. + + The mtext_ncmp () function is similar to mtext_cmp (), but + compares at most $N characters from the beginning. + + @return + This function returns 1, 0, or -1 if $MT1 is found greater than, + equal to, or less than $MT2, respectively. */ + +/***ja + @brief ��Ĥ� M-text ����Ƭ��ʬ��ʸ��ñ�̤���Ӥ���. + + �ؿ� mtext_ncmp () �ϡ��ؿ� mtext_cmp () Ʊ�ͤ� M-text + Ʊ�Τ���Ӥ���Ƭ������� $N ʸ���ޤǤ˴ؤ��ƹԤʤ��� + + @return + ���δؿ��ϡ�$MT1 �� $MT2 ����������� 0��$MT1 �� $MT2 ����礭����� + 1��$MT1 �� $MT2 ��꾮������� -1 ���֤��� + + @latexonly \IPAlabel{mtext_ncmp} @endlatexonly */ + +/*** + @seealso + mtext_cmp (), mtext_casecmp (), mtext_ncasecmp () + mtext_compare (), mtext_case_compare () */ + +int +mtext_ncmp (MText *mt1, MText *mt2, int n) +{ + if (n < 0) + return 0; + return compare (mt1, 0, (mt1->nchars < n ? mt1->nchars : n), + mt2, 0, (mt2->nchars < n ? mt2->nchars : n)); +} + +/*=*/ + +/***en + @brief Compare specified regions of two M-texts. + + The mtext_compare () function compares two M-texts $MT1 and $MT2, + character-by-character. The compared regions are between $FROM1 + and $TO1 in $MT1 and $FROM2 to $TO2 in MT2. $FROM1 and $FROM2 are + inclusive, $TO1 and $TO2 are exclusive. $FROM1 being equal to + $TO1 (or $FROM2 being equal to $TO2) means an M-text of length + zero. An invalid region specification is regarded as both $FROM1 + and $TO1 (or $FROM2 and $TO2) being 0. + + @return + This function returns 1, 0, or -1 if $MT1 is found greater than, + equal to, or less than $MT2, respectively. Comparison is based on + character codes. */ + +/***ja + @brief ��Ĥ� M-text �λ��ꤷ���ΰ�Ʊ�Τ���Ӥ���. + + �ؿ� mtext_compare () ����Ĥ� M-text $MT1 �� $MT2 + ��ʸ��ñ�̤���Ӥ��롣��Ӥ��оݤ� $MT1 �Τ��� $FROM1 ���� $TO1 �ޤǤȡ�$MT2 + �Τ��� $FROM2 ���� $TO2 �ޤǤǤ��롣$FROM1 �� $FROM2 �ϴޤޤ졢$TO1 + �� $TO2 �ϴޤޤ�ʤ���$FROM1 �� $TO1 �ʤ��뤤�� $FROM2 �� $TO2 + �ˤ�����������Ĺ�������� M-text ���̣���롣�ϰϻ���˸��꤬������ϡ� + $FROM1 �� $TO1 �ʤ��뤤�� $FROM2 �� $TO2 �� ξ���� 0 �����ꤵ�줿��ΤȤߤʤ��� + + @return + ���δؿ��ϡ�$MT1 �� $MT2 ����������� 0��$MT1 �� $MT2 ����礭����� + 1 ��$MT1 �� $MT2 ��꾮������� -1 ���֤�����Ӥ�ʸ�������ɤ˴�Ť��� */ + +/*** + @seealso + mtext_cmp (), mtext_ncmp (), mtext_casecmp (), mtext_ncasecmp (), + mtext_case_compare () */ + +int +mtext_compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2) +{ + if (from1 < 0 || from1 > to1 || to1 > mt1->nchars) + from1 = to1 = 0; + + if (from2 < 0 || from2 > to2 || to2 > mt2->nchars) + from2 = to2 = 0; + + return compare (mt1, from1, to1, mt2, from2, to2); +} + +/*=*/ + +/***en + @brief Search an M-text for a set of characters. + + The mtext_spn () function returns the length of the initial + segment of M-text $MT1 that consists entirely of characters in + M-text $MT2. */ + +/***ja + @brief ���뽸���ʸ���� M-text �����õ��. + + �ؿ� mtext_spn () �ϡ�M-text $MT1 ����Ƭ���� M-text $MT2 + �˴ޤޤ��ʸ�������ǤǤ��Ƥ�����ʬ��Ĺ�����֤��� + + @latexonly \IPAlabel{mtext_spn} @endlatexonly */ + +/*** + @seealso + mtext_cspn () */ + +int +mtext_spn (MText *mt, MText *accept) +{ + return span (mt, accept, 0, Mnil); +} + +/*=*/ + +/***en + @brief Search an M-text for the complement of a set of characters. + + The mtext_cspn () returns the length of the initial segment of + M-text $MT1 that consists entirely of characters not in M-text $MT2. */ + +/***ja + @brief ���뽸���°���ʤ�ʸ���� M-text �����õ��. + + �ؿ� mtext_cspn () �ϡ�M-text $MT1 ����Ƭ��ʬ�� M-text $MT2 + �˴ޤޤ�ʤ�ʸ�������ǤǤ��Ƥ�����ʬ��Ĺ�����֤��� + + @latexonly \IPAlabel{mtext_cspn} @endlatexonly */ + +/*** + @seealso + mtext_spn () */ + +int +mtext_cspn (MText *mt, MText *reject) +{ + return span (mt, reject, 0, Mt); +} + +/*=*/ + +/***en + @brief Search an M-text for any of a set of characters. + + The mtext_pbrk () function locates the first occurrence in M-text + $MT1 of any of the characters in M-text $MT2. + + @return + This function returns the position in $MT1 of the found character. + If no such character is found, it returns -1. */ + +/***ja + @brief ���뽸���°��ʸ���� M-text ���椫��õ��. + + �ؿ� mtext_pbrk () �ϡ�M-text $MT1 ��� M-text $MT2 + ��ʸ���Τɤ줫���ǽ�˸������֤�Ĵ�٤롣 + + @return + ���Ĥ��ä�ʸ���Ρ�$MT1 + ��ˤ�����и����֤��֤����⤷���Τ褦��ʸ�����ʤ���� -1 ���֤��� + + @latexonly \IPAlabel{mtext_pbrk} @endlatexonly */ + +int +mtext_pbrk (MText *mt, MText *accept) +{ + int nchars = mtext_nchars (mt); + int len = span (mt, accept, 0, Mt); + + return (len == nchars ? -1 : len); +} + +/*=*/ + +/***en + @brief Look for a token in an M-text. + + The mtext_tok () function searches a token that firstly occurs + after position $POS in M-text $MT. Here, a token means a + substring each of which does not appear in M-text $DELIM. Note + that the type of $POS is not @c int but pointer to @c int. + + @return + If a token is found, mtext_tok () copies the corresponding part of + $MT and returns a pointer to the copy. In this case, $POS is set + to the end of the found token. If no token is found, it returns + @c NULL without changing the external variable #merror_code. If an + error is detected, it returns @c NULL and assigns an error code + to the external variable #merror_code. */ + +/***ja + @brief M-text ��Υȡ������õ��. + + �ؿ� mtext_tok () �ϡ�M-text $MT ����ǰ��� $POS + �ʹߺǽ�˸����ȡ������õ���������ǥȡ�����Ȥ� M-text $DELIM + ����˸����ʤ�ʸ����������ʤ���ʬʸ����Ǥ��롣$POS �η��� @c int �ǤϤʤ��� @c + int �ؤΥݥ��󥿤Ǥ��뤳�Ȥ����ա� + + @return + �⤷�ȡ����󤬸��Ĥ���� mtext_tok ()�Ϥ��Υȡ����������������ʬ�� + $MT �򥳥ԡ��������Υ��ԡ��ؤΥݥ��󥿤��֤������ξ�硢$POS + �ϸ��Ĥ��ä��ȡ�����ν�ü�˥��åȤ���롣�ȡ����󤬸��Ĥ���ʤ��ä����ϳ����ѿ� + #merror_code ���Ѥ����� @c NULL ���֤������顼�����Ф��줿���� + @c NULL ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mtext_tok} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE */ + +MText * +mtext_tok (MText *mt, MText *delim, int *pos) +{ + int nchars = mtext_nchars (mt); + int pos2; + + M_CHECK_POS (mt, *pos, NULL); + + /* + Skip delimiters starting at POS in MT. + Never do *pos += span(...), or you will change *pos + even though no token is found. + */ + pos2 = *pos + span (mt, delim, *pos, Mnil); + + if (pos2 == nchars) + return NULL; + + *pos = pos2 + span (mt, delim, pos2, Mt); + return (insert (mtext (), 0, mt, pos2, *pos)); +} + +/*=*/ + +/***en + @brief Locate an M-text in another. + + The mtext_text () function finds the first occurrence of M-text + $MT2 in M-text $MT1 after the position $POS while ignoring + difference of the text properties. + + @return + If $MT2 is found in $MT1, mtext_text () returns the position of it + first occurrence. Otherwise it returns -1. If $MT2 is empty, it + returns 0. */ + +/***ja + @brief M-text ����̤� M-text ��õ��. + + �ؿ� mtext_text () �ϡ�M-text $MT1 ��ǰ��� $POS �ʹߤ˸����� + M-text $MT2 �κǽ�ΰ��֤�Ĵ�٤롣�ƥ����ȥץ��ѥƥ��ΰ㤤��̵�뤵��롣 + + @return + $MT1 ��� $MT2 �����Ĥ���С�mtext_text() + �Ϥ��κǽ�νи����֤��֤������Ĥ���ʤ����� -1 ���֤����⤷ $MT2 �����ʤ�� 0 ���֤��� + + @latexonly \IPAlabel{mtext_text} @endlatexonly */ + +int +mtext_text (MText *mt1, int pos, MText *mt2) +{ + int from = pos; + int c = mtext_ref_char (mt2, 0); + int nbytes2 = mtext_nbytes (mt2); + int limit; + int use_memcmp = (mt1->format == mt2->format + || (mt1->format < MTEXT_FORMAT_UTF_8 + && mt2->format == MTEXT_FORMAT_UTF_8)); + int unit_bytes = UNIT_BYTES (mt1->format); + + if (from + mtext_nchars (mt2) > mtext_nchars (mt1)) + return -1; + limit = mtext_nchars (mt1) - mtext_nchars (mt2) + 1; + + while (1) + { + int pos_byte; + + if ((pos = mtext_character (mt1, from, limit, c)) < 0) + return -1; + pos_byte = POS_CHAR_TO_BYTE (mt1, pos); + if (use_memcmp + ? ! memcmp (mt1->data + pos_byte * unit_bytes, + mt2->data, nbytes2 * unit_bytes) + : ! compare (mt1, pos, mt2->nchars, mt2, 0, mt2->nchars)) + break; + from = pos + 1; + } + return pos; +} + +/***en + @brief Locate an M-text in a specific range of another. + + The mtext_search () function searches for the first occurrence of + M-text $MT2 in M-text $MT1 in the region $FROM and $TO while + ignoring difference of the text properties. If $FROM is less than + $TO, the forward search starts from $FROM, otherwise the backward + search starts from $TO. + + @return + If $MT2 is found in $MT1, mtext_search () returns the position of the + first occurrence. Otherwise it returns -1. If $MT2 is empty, it + returns 0. */ + +/***ja + @brief M-text ���������ΰ���̤� M-text ��õ��. + + �ؿ� mtext_search () �ϡ�M-text $MT1 ��� $FROM ���� $TO + �ޤǤδ֤��ΰ��M-text $MT2 + ���ǽ�˸�������֤�Ĵ�٤롣�ƥ����ȥץ��ѥƥ��ΰ㤤��̵�뤵��롣�⤷ + $FROM �� $TO ��꾮�������õ���ϰ��� $FROM �������������ء������Ǥʤ���� + $TO ������Ƭ�����ؿʤࡣ + + @return + $MT1 ��� $MT2 �����Ĥ���С�mtext_search() + �Ϥ��κǽ�νи����֤��֤������Ĥ���ʤ����� -1 ���֤����⤷ $MT2 �����ʤ�� 0 ���֤��� + */ + +int +mtext_search (MText *mt1, int from, int to, MText *mt2) +{ + int c = mtext_ref_char (mt2, 0); + int from_byte; + int nbytes2 = mtext_nbytes (mt2); + + if (mt1->format > MTEXT_FORMAT_UTF_8 + || mt2->format > MTEXT_FORMAT_UTF_8) + MERROR (MERROR_MTEXT, -1); + + if (from < to) + { + to -= mtext_nchars (mt2); + if (from > to) + return -1; + while (1) + { + if ((from = find_char_forward (mt1, from, to, c)) < 0) + return -1; + from_byte = POS_CHAR_TO_BYTE (mt1, from); + if (! memcmp (mt1->data + from_byte, mt2->data, nbytes2)) + break; + from++; + } + } + else if (from > to) + { + from -= mtext_nchars (mt2); + if (from < to) + return -1; + while (1) + { + if ((from = find_char_backward (mt1, to, from + 1, c)) < 0) + return -1; + from_byte = POS_CHAR_TO_BYTE (mt1, from); + if (! memcmp (mt1->data + from_byte, mt2->data, nbytes2)) + break; + from--; + } + } + + return from; +} + +/*=*/ + +/***en + @brief Compare two M-texts ignoring cases. + + The mtext_casecmp () function is similar to mtext_cmp (), but + ignores cases on comparison. + + @return + This function returns 1, 0, or -1 if $MT1 is found greater than, + equal to, or less than $MT2, respectively. */ + +/***ja + @brief ��Ĥ� M-text ����ʸ������ʸ���ζ��̤�̵�뤷����Ӥ���. + + �ؿ� mtext_casecmp () �ϡ��ؿ� mtext_cmp () Ʊ�ͤ� M-text + Ʊ�Τ���Ӥ���ʸ������ʸ���ζ��̤�̵�뤷�ƹԤʤ��� + + @return + ���δؿ��ϡ�$MT1 �� $MT2 ����������� 0��$MT1 �� $MT2 + ����礭����� 1��$MT1 �� $MT2 ��꾮������� -1 ���֤��� + + @latexonly \IPAlabel{mtext_casecmp} @endlatexonly */ + +/*** + @seealso + mtext_cmp (), mtext_ncmp (), mtext_ncasecmp () + mtext_compare (), mtext_case_compare () */ + +int +mtext_casecmp (MText *mt1, MText *mt2) +{ + return case_compare (mt1, 0, mt1->nchars, mt2, 0, mt2->nchars); +} + +/*=*/ + +/***en + @brief Compare initial parts of two M-texts ignoring cases. + + The mtext_ncasecmp () function is similar to mtext_casecmp (), but + compares at most $N characters from the beginning. + + @return + This function returns 1, 0, or -1 if $MT1 is found greater than, + equal to, or less than $MT2, respectively. */ + +/***ja + @brief ��Ĥ� M-text ����Ƭ��ʬ����ʸ������ʸ���ζ��̤�̵�뤷����Ӥ���. + + �ؿ� mtext_ncasecmp () �ϡ��ؿ� mtext_casecmp () Ʊ�ͤ� M-text + Ʊ�Τ���Ӥ���Ƭ������� $N ʸ���ޤǤ˴ؤ��ƹԤʤ��� + + @return + ���δؿ��ϡ�$MT1 �� $MT2 ����������� 0��$MT1 �� $MT2 + ����礭����� 1��$MT1 �� $MT2 ��꾮������� -1 ���֤��� + + @latexonly \IPAlabel{mtext_ncasecmp} @endlatexonly */ + +/*** + @seealso + mtext_cmp (), mtext_casecmp (), mtext_casecmp () + mtext_compare (), mtext_case_compare () */ + +int +mtext_ncasecmp (MText *mt1, MText *mt2, int n) +{ + if (n < 0) + return 0; + return case_compare (mt1, 0, (mt1->nchars < n ? mt1->nchars : n), + mt2, 0, (mt2->nchars < n ? mt2->nchars : n)); +} + +/*=*/ + +/***en + @brief Compare specified regions of two M-texts ignoring cases. + + The mtext_case_compare () function compares two M-texts $MT1 and + $MT2, character-by-character, ignoring cases. The compared + regions are between $FROM1 and $TO1 in $MT1 and $FROM2 to $TO2 in + MT2. $FROM1 and $FROM2 are inclusive, $TO1 and $TO2 are + exclusive. $FROM1 being equal to $TO1 (or $FROM2 being equal to + $TO2) means an M-text of length zero. An invalid region + specification is regarded as both $FROM1 and $TO1 (or $FROM2 and + $TO2) being 0. + + @return + This function returns 1, 0, or -1 if $MT1 is found greater than, + equal to, or less than $MT2, respectively. Comparison is based on + character codes. */ + +/***ja + @brief ��Ĥ� M-text �λ��ꤷ���ΰ����ʸ������ʸ���ζ��̤�̵�뤷����Ӥ���. + + �ؿ� mtext_compare () ����Ĥ� M-text $MT1 �� $MT2 + ����ʸ������ʸ���ζ��̤�̵�뤷��ʸ��ñ�̤���Ӥ��롣��Ӥ��оݤ� $MT1 + �� $FROM1 ���� $TO1 �ޤǡ�$MT2 �� $FROM2 ���� $TO2 �ޤǤǤ��롣 + $FROM1 �� $FROM2 �ϴޤޤ졢$TO1 �� $TO2 �ϴޤޤ�ʤ���$FROM1 �� $TO1 + �ʤ��뤤�� $FROM2 �� $TO2 �ˤ�����������Ĺ�������� M-text + ���̣���롣�ϰϻ���˸��꤬������ϡ�$FROM1 �� $TO1 �ʤ��뤤�� + $FROM2 �� $TO2 ��ξ���� 0 �����ꤵ�줿��Τȸ��ʤ��� + + @return + ���δؿ��ϡ�$MT1 �� $MT2 ����������� 0��$MT1 �� $MT2 ����礭����� + 1��$MT1 �� $MT2 ��꾮������� -1���֤�����Ӥ�ʸ�������ɤ˴�Ť��� + + @latexonly \IPAlabel{mtext_case_compare} @endlatexonly +*/ + +/*** + @seealso + mtext_cmp (), mtext_ncmp (), mtext_casecmp (), mtext_ncasecmp (), + mtext_compare () */ + +int +mtext_case_compare (MText *mt1, int from1, int to1, + MText *mt2, int from2, int to2) +{ + if (from1 < 0 || from1 > to1 || to1 > mt1->nchars) + from1 = to1 = 0; + + if (from2 < 0 || from2 > to2 || to2 > mt2->nchars) + from2 = to2 = 0; + + return case_compare (mt1, from1, to1, mt2, from2, to2); +} + +/*=*/ + +/***en + @brief Lowercase an M-text. + + The mtext_lowercase () function destructively converts each + character in M-text $MT to lowercase. Adjacent characters in $MT + may affect the case conversion. If the Mlanguage text property is + attached to $MT, it may also affect the conversion. The length of + $MT may change. Characters that cannot be converted to lowercase + is left unchanged. All the text properties are inherited. + + @return + This function returns the length of the updated $MT. +*/ + +/***ja + @brief M-text ��ʸ���ˤ���. + + �ؿ� mtext_lowercase () �� M-text $MT ��γ�ʸ�����˲�Ū�˾�ʸ������ + �����롣�Ѵ��˺ݤ������ܤ���ʸ���αƶ�������뤳�Ȥ����롣$MT �˥� + �����ȥץ��ѥƥ� Mlanguage ���դ��Ƥ�����ϡ�������Ѵ��˱ƶ��� + Ϳ�����롣$MT ��Ĺ�����Ѥ�뤳�Ȥ����롣��ʸ�����Ѵ��Ǥ��ʤ��ä�ʸ + ���Ϥ��Τޤ޻Ĥ롣�ƥ����ȥץ��ѥƥ��Ϥ��٤ƷѾ�����롣 + + @return + ���δؿ��Ϲ������ $MT ��Ĺ�����֤��� +*/ + +/*** + @seealso + mtext_titlecase (), mtext_uppercase () +*/ + +int +mtext_lowercase (MText *mt) + +{ + CASE_CONV_INIT (-1); + + return mtext__lowercase (mt, 0, mtext_len (mt)); +} + +/*=*/ + +/***en + @brief Titlecase an M-text. + + The mtext_titlecase () function destructively converts the first + character with the cased property in M-text $MT to titlecase and + the others to lowercase. The length of $MT may change. If the + character cannot be converted to titlecase, it is left unchanged. + All the text properties are inherited. + + @return + This function returns the length of the updated $MT. +*/ + +/***ja + @brief M-text �򥿥��ȥ륱�����ˤ���. + + �ؿ� mtext_titlecase () �� M-text $MT ��� cased �ץ��ѥƥ������ + �ǽ��ʸ���򥿥��ȥ륱�����ˡ������Ƥ���ʹߤ�ʸ����ʸ�����˲�Ū + ���Ѵ����롣$MT ��Ĺ�����Ѥ�뤳�Ȥ����롣�����ȥ륱�����ˤ��Ѵ��� + ���ʤ��ä����Ϥ��Τޤޤ��Ѥ��ʤ����ƥ����ȥץ��ѥƥ��Ϥ��٤Ʒ� + ������롣 + + @return + ���δؿ��Ϲ������ $MT ��Ĺ�����֤��� +*/ + +/*** + @seealso + mtext_lowercase (), mtext_uppercase () +*/ + +int +mtext_titlecase (MText *mt) +{ + int len = mtext_len (mt), from, to; + + CASE_CONV_INIT (-1); + + /* Find 1st cased character. */ + for (from = 0; from < len; from++) + { + int csd = (int) mchartable_lookup (cased, mtext_ref_char (mt, from)); + + if (csd > 0 && csd & CASED) + break; + } + + if (from == len) + return len; + + if (from == len - 1) + return (mtext__titlecase (mt, from, len)); + + /* Go through following combining characters. */ + for (to = from + 1; + (to < len + && ((int) mchartable_lookup (combining_class, mtext_ref_char (mt, to)) + > 0)); + to++); + + /* Titlecase the region and prepare for next lowercase operation. + MT may be shortened or lengthened. */ + from = mtext__titlecase (mt, from, to); + + return (mtext__lowercase (mt, from, mtext_len (mt))); +} + +/*=*/ + +/***en + @brief Uppercase an M-text. + + + The mtext_uppercase () function destructively converts each + character in M-text $MT to uppercase. Adjacent characters in $MT + may affect the case conversion. If the Mlanguage text property is + attached to $MT, it may also affect the conversion. The length of + $MT may change. Characters that cannot be converted to uppercase + is left unchanged. All the text properties are inherited. + + @return + This function returns the length of the updated $MT. +*/ + +/***ja + @brief M-text ����ʸ���ˤ���. + + �ؿ� mtext_uppercase () �� M-text $MT ��γ�ʸ�����˲�Ū����ʸ������ + �����롣�Ѵ��˺ݤ������ܤ���ʸ���αƶ�������뤳�Ȥ����롣$MT �˥� + �����ȥץ��ѥƥ� Mlanguage ���դ��Ƥ�����ϡ�������Ѵ��˱ƶ��� + Ϳ�����롣$MT ��Ĺ�����Ѥ�뤳�Ȥ����롣��ʸ�����Ѵ��Ǥ��ʤ��ä�ʸ + ���Ϥ��Τޤ޻Ĥ롣�ƥ����ȥץ��ѥƥ��Ϥ��٤ƷѾ�����롣 + + @return + ���δؿ��Ϲ������ $MT ��Ĺ�����֤��� +*/ + +/*** + @seealso + mtext_lowercase (), mtext_titlecase () +*/ + +int +mtext_uppercase (MText *mt) +{ + CASE_CONV_INIT (-1); + + return (mtext__uppercase (mt, 0, mtext_len (mt))); +} + +/*** @} */ + +#include + +/*** @addtogroup m17nDebug */ +/*=*/ +/*** @{ */ + +/***en + @brief Dump an M-text. + + The mdebug_dump_mtext () function prints the M-text $MT in a human + readable way to the stderr or to what specified by the environment + variable MDEBUG_OUTPUT_FILE. $INDENT specifies how many columns + to indent the lines but the first one. If $FULLP is zero, this + function prints only a character code sequence. Otherwise, it + prints the internal byte sequence and text properties as well. + + @return + This function returns $MT. */ +/***ja + @brief M-text �����פ���. + + �ؿ� mdebug_dump_mtext () �� M-text $MT ��ɸ�२�顼���Ϥ⤷���ϴ� + ���ѿ� MDEBUG_DUMP_FONT �ǻ��ꤵ�줿�ե�����˿ʹ֤˲��ɤʷ��ǰ��� + ���롣 $INDENT �ϣ����ܰʹߤΥ���ǥ�Ȥ���ꤹ�롣$FULLP �� 0 �ʤ� + �С�ʸ���������������������롣�����Ǥʤ���С������Х�����ȥƥ� + ���ȥץ��ѥƥ���������롣 + + @return + ���δؿ��� $MT ���֤��� */ + +MText * +mdebug_dump_mtext (MText *mt, int indent, int fullp) +{ + int i; + + if (! fullp) + { + fprintf (mdebug__output, "\""); + for (i = 0; i < mt->nchars; i++) + { + int c = mtext_ref_char (mt, i); + + if (c == '"' || c == '\\') + fprintf (mdebug__output, "\\%c", c); + else if ((c >= ' ' && c < 127) || c == '\n') + fprintf (mdebug__output, "%c", c); + else + fprintf (mdebug__output, "\\x%02X", c); + } + fprintf (mdebug__output, "\""); + return mt; + } + + fprintf (mdebug__output, + "(mtext (size %d %d %d) (cache %d %d)", + mt->nchars, mt->nbytes, mt->allocated, + mt->cache_char_pos, mt->cache_byte_pos); + + if (mt->nchars > 0) + { + char *prefix = (char *) alloca (indent + 1); + unsigned char *p; + + memset (prefix, 32, indent); + prefix[indent] = 0; + + fprintf (mdebug__output, "\n%s (bytes \"", prefix); + for (i = 0; i < mt->nbytes; i++) + fprintf (mdebug__output, "\\x%02x", mt->data[i]); + fprintf (mdebug__output, "\")\n"); + fprintf (mdebug__output, "%s (chars \"", prefix); + p = mt->data; + for (i = 0; i < mt->nchars; i++) + { + int len; + int c = STRING_CHAR_AND_BYTES (p, len); + + if (c == '"' || c == '\\') + fprintf (mdebug__output, "\\%c", c); + else if (c >= ' ' && c < 127) + fputc (c, mdebug__output); + else + fprintf (mdebug__output, "\\x%X", c); + p += len; + } + fprintf (mdebug__output, "\")"); + if (mt->plist) + { + fprintf (mdebug__output, "\n%s ", prefix); + dump_textplist (mt->plist, indent + 1); + } + } + fprintf (mdebug__output, ")"); + return mt; +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/mtext.h b/src/mtext.h new file mode 100644 index 0000000..4a3e772 --- /dev/null +++ b/src/mtext.h @@ -0,0 +1,71 @@ +/* mtext.h -- header file for the M-text module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_MTEXT_H_ +#define _M17N_MTEXT_H_ + +/** @file mtext.h + @brief Header for M-text handling. +*/ + +#define POS_CHAR_TO_BYTE(mt, pos) \ + (mtext_nchars (mt) == mtext_nbytes (mt) ? (pos) \ + : (pos) == (mt)->cache_char_pos ? (mt)->cache_byte_pos \ + : mtext__char_to_byte ((mt), (pos))) + +#define POS_BYTE_TO_CHAR(mt, pos_byte) \ + (mtext_nchars (mt) == mtext_nbytes (mt) ? (pos_byte) \ + : (pos_byte) == (mt)->cache_byte_pos ? (mt)->cache_char_pos \ + : mtext__byte_to_char ((mt), (pos_byte))) + + +#define MTEXT_DATA(mt) ((mt)->data) + +extern int mtext__char_to_byte (MText *mt, int pos); + +extern int mtext__byte_to_char (MText *mt, int pos_byte); + +extern void mtext__enlarge (MText *mt, int nbytes); + +extern int mtext__takein (MText *mt, int nchars, int nbytes); + +extern int mtext__cat_data (MText *mt, unsigned char *p, int nbytes, + enum MTextFormat format); + +#define MTEXT_CAT_ASCII(mt, str) \ + mtext__cat_data ((mt), (unsigned char *) (str), strlen (str), \ + MTEXT_FORMAT_US_ASCII) + +extern MText *mtext__from_data (const void *data, int nitems, + enum MTextFormat format, int need_copy); + +extern void mtext__adjust_format (MText *mt, enum MTextFormat format); + +extern int mtext__bol (MText *mt, int pos); + +extern int mtext__eol (MText *mt, int pos); + +extern void mtext__wseg_fini (); + +extern int mtext__word_segment (MText *mt, int pos, int *from, int *to); + +#endif /* _M17N_MTEXT_H_ */ diff --git a/src/plist.c b/src/plist.c new file mode 100644 index 0000000..6256a7e --- /dev/null +++ b/src/plist.c @@ -0,0 +1,1686 @@ +/* plist.c -- plist module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nPlist + + @brief Property List objects and API for them. + + A @e property @e list (or @e plist for short) is a list of zero or + more properties. A property consists of a @e key and a @e value, + where key is a symbol and value is anything that can be cast to + (void *). + + If the key of a property is a @e managing @e key, its @e value is + a @e managed @e object. A property list itself is a managed + objects. + + If each key of a plist is one of #Msymbol, #Mtext, #Minteger, and + #Mplist, the plist is called as @e well-formed and represented by + the following notation in the documentation. + +@verbatim + PLIST ::= '(' ELEMENT * ')' + + ELEMENT ::= INTEGER | SYMBOL | M-TEXT | PLIST + + M-TEXT ::= '"' text data ... '"' +@endverbatim + + For instance, if a plist has four elements; integer -20, symbol of + name "sym", M-text of contents "abc", and plist of integer 10 and + symbol of name "another-symbol", it is represented as this: + + (-20 sym "abc" (10 another-symbol)) + + */ +/***ja + @addtogroup m17nPlist + + @brief �ץ��ѥƥ��ꥹ�ȥ��֥������ȤȤ���˴ؤ��� API. + + @e �ץ��ѥƥ��ꥹ�� (�ޤ��� @e plist) �� 0 + �İʾ�Υץ��ѥƥ��Υꥹ�ȤǤ��롣�ץ��ѥƥ��� @e ���� �� @e �� + ����ʤ롣�����ϥ���ܥ�Ǥ��ꡢ�ͤ� (void *) + �˥��㥹�ȤǤ����Τʤ�в��Ǥ��ɤ��� + + ����ץ��ѥƥ��Υ����� @e �������� �ʤ�С����� @e �� �� @e ������ + @e ���֥������� + �Ǥ��롣�ץ��ѥƥ��ꥹ�ȼ��Τ���������֥������ȤǤ��롣 */ + +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include + +#include "config.h" +#include "m17n.h" +#include "m17n-misc.h" +#include "internal.h" +#include "character.h" +#include "mtext.h" +#include "symbol.h" +#include "plist.h" + +static M17NObjectArray plist_table; + +/** Set PLIST to a newly allocated plist object. */ + +#define MPLIST_NEW(plist) \ + do { \ + M17N_OBJECT (plist, free_plist, MERROR_PLIST); \ + M17N_OBJECT_REGISTER (plist_table, plist); \ + } while (0) + + +/** Set the element of PLIST to KEY and VAL. If PLIST is an anchor, + append a new anchor. */ + +#define MPLIST_SET(plist, key, val) \ + do { \ + MPLIST_KEY (plist) = (key); \ + MPLIST_VAL (plist) = (val); \ + if (! (plist)->next) \ + MPLIST_NEW ((plist)->next); \ + } while (0) + + +/** Set the element of PLIST to KEY and VAL. PLIST must be an anchor. + Append a new anchor and set PLIST to that anchor. */ + +#define MPLIST_SET_ADVANCE(plist, key, val) \ + do { \ + MPLIST_KEY (plist) = (key); \ + MPLIST_VAL (plist) = (val); \ + MPLIST_NEW ((plist)->next); \ + plist = (plist)->next; \ + } while (0) + + +static void +free_plist (void *object) +{ + MPlist *plist = (MPlist *) object; + + do { + MPlist *next = plist->next; + + if (MPLIST_KEY (plist) != Mnil + && MPLIST_KEY (plist)->managing_key) + M17N_OBJECT_UNREF (MPLIST_VAL (plist)); + M17N_OBJECT_UNREGISTER (plist_table, plist); + free (plist); + plist = next; + } while (plist && plist->control.ref_count == 1); + M17N_OBJECT_UNREF (plist); +} + + + +/* Load a plist from a string. */ + +#define READ_CHUNK 0x10000 + +typedef struct +{ + /* File pointer if the stream is associated with a file. Otherwise + NULL. */ + FILE *fp; + int eof; + unsigned char buffer[READ_CHUNK]; + unsigned char *p, *pend; +} MStream; + +static int +get_byte (MStream *st) +{ + int n; + + if (! st->fp || st->eof) + return EOF; + n = fread (st->buffer, 1, READ_CHUNK, st->fp); + if (n <= 0) + { + st->eof = 1; + return EOF; + } + st->p = st->buffer + 1; + st->pend = st->buffer + n; + return st->buffer[0]; +} + +#define GETC(st) ((st)->p < (st)->pend ? *(st)->p++ : get_byte (st)) + +#define UNGETC(c, st) (--((st)->p)) + +/** Mapping table for reading a number. Hexadecimal chars + (0..9,A..F,a..F) are mapped to the corresponding numbers. + Apostrophe (code 39) is mapped to 254. All the other bytes are + mapped to 255. */ +unsigned char hex_mnemonic[256]; + +/** Mapping table for escaped characters. Mnemonic characters (e, b, + f, n, r, or t) that follows '\' are mapped to the corresponding + character code. All the other bytes are mapped to themselves. */ +unsigned char escape_mnemonic[256]; + + +/** Read an integer from the stream ST. It is assumed that we have + already read one character C. */ + +static int +read_decimal (MStream *st, int c) +{ + int num = 0; + + while (c >= '0' && c <= '9') + { + num = (num * 10) + (c - '0'); + c = GETC (st); + } + + if (c != EOF) + UNGETC (c, st); + return num; +} + +/** Read an unsigned from the stream ST. */ + +static unsigned +read_hexadesimal (MStream *st) +{ + int c; + unsigned num = 0, n; + + while ((c = GETC (st)) != EOF + && (n = hex_mnemonic[c]) < 16) + num = (num << 4) | n; + if (c != EOF) + UNGETC (c, st); + return num; +} + + +/** Read an M-text element from ST, and add it to LIST. Return a list + for the next element. */ + +#define READ_MTEXT_BUF_SIZE 256 + +static MPlist * +read_mtext_element (MPlist *plist, MStream *st, int skip) +{ + unsigned char buffer[READ_MTEXT_BUF_SIZE], *buf = buffer; + int nbytes = READ_MTEXT_BUF_SIZE; + int c, i; + + i = 0; + while ((c = GETC (st)) != EOF && c != '"') + { + int is_char = 0; + + if (c == '\\') + { + c = GETC (st); + if (c == EOF) + break; + if (c == '\n') + continue; + if (c == 'x' || c == 'u') + { + int next_c; + + c = read_hexadesimal (st); + next_c = GETC (st); + if (next_c != ' ') + UNGETC (next_c, st); + if (c >= 0x80) + is_char = 1; + } + else + c = escape_mnemonic[c]; + } + + if (! skip) + { + if (i + MAX_UTF8_CHAR_BYTES + 1 >= nbytes) + { + if (buf == buffer) + { + nbytes *= 2; + buf = malloc (nbytes); + memcpy (buf, buffer, i); + } + else + { + nbytes += READ_MTEXT_BUF_SIZE; + buf = realloc (buf, nbytes); + } + } + + if (is_char) + i += CHAR_STRING_UTF8 (c, buf); + else + buf[i++] = c; + } + } + + if (! skip) + { + MText *mt; + + buf[i] = 0; + mt = mtext__from_data (buf, i, MTEXT_FORMAT_UTF_8, (buf == buffer)); + if (buf != buffer) + mt->allocated = nbytes; + MPLIST_SET_ADVANCE (plist, Mtext, mt); + } + return plist; +} + +static int +read_character (MStream *st, int c) +{ + unsigned char buf[MAX_UTF8_CHAR_BYTES + 1]; + int len = CHAR_BYTES_BY_HEAD (c); + int i; + + buf[0] = c; + for (i = 1; i < len; i++) + { + c = GETC (st); + if (c == EOF + || (c & 0xC0) != 0x80) + break; + buf[i] = c; + } + if (i == len) + c = STRING_CHAR_UTF8 (buf); + else + c = buf[0]; + return c; +} + + +/** Read a symbol element from ST, and add it to LIST. Return a list + for the next element. */ + +static MPlist * +read_symbol_element (MPlist *plist, MStream *st, int c, int skip) +{ + unsigned char buffer[1024]; + int bufsize = 1024; + unsigned char *buf = buffer; + int i; + + i = 0; + while (c != EOF + && c > ' ' + && c != ')' && c != '(' && c != '"') + { + if (i >= bufsize) + { + bufsize *= 2; + if (buf == buffer) + { + MTABLE_MALLOC (buf, bufsize, MERROR_PLIST); + memcpy (buf, buffer, i); + } + else + MTABLE_REALLOC (buf, bufsize, MERROR_PLIST); + } + if (c == '\\') + { + c = GETC (st); + if (c == EOF) + break; + c = escape_mnemonic[c]; + } + if (! skip) + buf[i++] = c; + c = GETC (st); + } + + if (c > ' ') + UNGETC (c, st); + if (! skip) + { + buf[i] = 0; + MPLIST_SET_ADVANCE (plist, Msymbol, msymbol ((char *) buf)); + if (buf != buffer) + free (buf); + } + return plist; +} + +/** Read an integer element from ST, and add it to LIST. Return a + list for the next element. It is assumed that we have already + read the character C. */ + +static MPlist * +read_integer_element (MPlist *plist, MStream *st, int c, int skip) +{ + int num; + + if (c == '#') + { + c = GETC (st); + if (c != 'x') + { + UNGETC (c, st); + return read_symbol_element (plist, st, '#', skip); + } + num = read_hexadesimal (st); + } + else if (c == '0') + { + c = GETC (st); + num = (c == 'x' ? read_hexadesimal (st) : read_decimal (st, c)); + } + else if (c == '?') + { + c = GETC (st); + if (c == EOF) + num = 0; + else if (c != '\\') + { + if (c < 128 || ! CHAR_UNITS_BY_HEAD_UTF8 (c)) + num = c; + else + num = read_character (st, c); + } + else + { + c = GETC (st); + if (c == EOF) + num = '\\'; + else if (c < 128 || ! CHAR_UNITS_BY_HEAD_UTF8 (c)) + num = escape_mnemonic[c]; + else + num = read_character (st, c); + } + } + else if (c == '-') + { + c = GETC (st); + if (c < '0' || c > '9') + { + UNGETC (c, st); + return read_symbol_element (plist, st, '-', skip); + } + num = - read_decimal (st, c); + } + else + num = read_decimal (st, c); + + if (! skip) + MPLIST_SET_ADVANCE (plist, Minteger, (void *) num); + return plist; +} + +/* Read an element of various type from stream ST, and add it to LIST. + Return a list for the next element. The element type is decided by + the first token character found as below: + '(': plist + '"': mtext + '0'..'9', '-': integer + '?': integer representing character code + the other ASCII letters: symbol + + If KEYS is not NULL, it is a plist contains target keys and stop + keys. In this caes, read only a plist whose key has value 1 in + KEYS, and return NULL when we encounter a plist whose key has value + 0 in KEYS while skipping any other elements. */ + +static MPlist * +read_element (MPlist *plist, MStream *st, MPlist *keys) +{ + int c; + + /* Skip separators and comments. */ + while (1) + { + while ((c = GETC (st)) != EOF && c <= ' '); + if (c != ';') + break; + while ((c = GETC (st)) != EOF && c != '\n'); + if (c == EOF) + break; + } + + if (c == '(') + { + MPlist *pl, *p; + + MPLIST_NEW (pl); + p = pl; + p = read_element (p, st, NULL); + if (keys && p && MPLIST_SYMBOL_P (pl)) + { + if (MPLIST_TAIL_P (keys)) + { + while ((p = read_element (p, st, NULL))); + MPLIST_SET_ADVANCE (plist, Mplist, pl); + return NULL; + } + else + { + MPlist *p0 = keys; + + MPLIST_FIND (p0, MPLIST_SYMBOL (pl)); + if (! MPLIST_TAIL_P (p0) && ! MPLIST_VAL (p0)) + { + M17N_OBJECT_UNREF (pl); + return NULL; + } + while ((p = read_element (p, st, NULL))); + if (! MPLIST_TAIL_P (p0)) + { + MPLIST_SET_ADVANCE (plist, Mplist, pl); + return NULL; + } + else + M17N_OBJECT_UNREF (pl); + } + } + else + { + if (p) + while ((p = read_element (p, st, NULL))); + MPLIST_SET_ADVANCE (plist, Mplist, pl); + } + return plist; + } + if (c == '"') + return (read_mtext_element (plist, st, keys ? 1 : 0)); + if ((c >= '0' && c <= '9') || c == '-' || c == '?' || c == '#') + return (read_integer_element (plist, st, c, keys ? 1 : 0)); + if (c == EOF || c == ')') + return NULL; + return (read_symbol_element (plist, st, c, keys ? 1 : 0)); +} + +#define PUTC(MT, C) \ + do { \ + if (MT) \ + mtext_cat_char ((MT), (C)); \ + else \ + putc ((C), mdebug__output); \ + } while (0); + +#define PUTS(MT, STR) \ + do { \ + if (MT) \ + MTEXT_CAT_ASCII ((MT), (STR)); \ + else \ + fputs ((STR), mdebug__output); \ + } while (0) + + +static void +write_symbol (MText *mt, MSymbol sym) +{ + if (sym == Mnil) + { + PUTS (mt, "nil"); + } + else + { + char *name = MSYMBOL_NAME (sym); + + if (isdigit (*name)) + PUTC (mt, '\\'); + while (*name) + { + if (*name <= ' ' || *name == '\\' || *name == '"' + || *name == '(' || *name == ')') + PUTC (mt, '\\'); + PUTC (mt, *name); + name++; + } + } +} + +static void +write_element (MText *mt, MPlist *plist, int indent) +{ + if (MPLIST_SYMBOL_P (plist)) + { + write_symbol (mt, MPLIST_SYMBOL (plist)); + } + else if (MPLIST_INTEGER_P (plist)) + { + int num = MPLIST_INTEGER (plist); + char buf[128]; + + sprintf (buf, "%d", num); + PUTS (mt, buf); + } + else if (MPLIST_PLIST_P (plist) + || MPLIST_NESTED_P (plist)) + { + MPlist *pl; + int newline = 0; + + if (MPLIST_NESTED_P (plist)) + { + write_symbol (mt, MPLIST_KEY (plist)); + PUTC (mt, ':'); + } + plist = MPLIST_PLIST (plist); + PUTC (mt, '('); + if (indent >= 0) + indent++; + MPLIST_DO (pl, plist) + { + if (pl != plist) + { + if (indent > 0 && (MPLIST_PLIST_P (pl) || MPLIST_MTEXT_P (pl))) + newline = 1; + if (newline) + { + int i; + + PUTC (mt, '\n'); + for (i = 1; i < indent; i++) + PUTC (mt, ' '); + } + PUTC (mt, ' '); + } + write_element (mt, pl, indent); + if (indent >= 0) + newline = (MPLIST_PLIST_P (pl) || MPLIST_MTEXT_P (pl)); + } + PUTC (mt, ')'); + } + else if (MPLIST_MTEXT_P (plist)) + { + MText *this_mt = MPLIST_MTEXT (plist); + int from = 0, to = mtext_nchars (this_mt); + int stop1 = 0, stop2 = 0; + + if (! mt && this_mt->format > MTEXT_FORMAT_UTF_8) + { + this_mt = mtext_dup (this_mt); + mtext__adjust_format (this_mt, MTEXT_FORMAT_UTF_8); + } + + PUTC (mt, '"'); + while (1) + { + int stop, escaped; + + if (from == stop1) + { + if ((stop1 = mtext_character (this_mt, from, to, '"')) < 0) + stop1 = to; + } + if (from == stop2) + { + if ((stop2 = mtext_character (this_mt, from, to, '\\')) < 0) + stop2 = to; + } + if (stop1 < stop2) + stop = stop1++, escaped = '"'; + else + stop = stop2++, escaped = '\\'; + if (mt) + mtext_copy (mt, mtext_nchars (mt), this_mt, from, stop); + else + { + unsigned char *data = MTEXT_DATA (this_mt); + unsigned char *beg = data + mtext__char_to_byte (this_mt, from); + unsigned char *end = data + mtext__char_to_byte (this_mt, stop); + + while (beg < end) + putc (*beg, mdebug__output), beg++; + } + if (stop == to) + break; + PUTC (mt, '\\'); + PUTC (mt, escaped); + from = stop + 1; + } + PUTC (mt, '"'); + if (this_mt != MPLIST_MTEXT (plist)) + M17N_OBJECT_UNREF (this_mt); + } + else if (MPLIST_STRING_P (plist)) + { + char *str = MPLIST_STRING (plist); + + if (mt) + { + MText *this_mt = mtext__from_data (str, strlen (str), + MTEXT_FORMAT_UTF_8, 0); + + mtext_copy (mt, mtext_nchars (mt), + this_mt, 0, mtext_nchars (this_mt)); + M17N_OBJECT_UNREF (this_mt); + } + else + fprintf (mdebug__output, "%s", str); + } + else + { + char buf[128]; + + write_symbol (mt, MPLIST_KEY (plist)); + PUTC (mt, ':'); + sprintf (buf, "%04X", (unsigned) MPLIST_VAL (plist)); + PUTS (mt, buf); + } +} + + +/* Internal API */ +int +mplist__init () +{ + int i; + + M17N_OBJECT_ADD_ARRAY (plist_table, "Plist"); + + Minteger = msymbol ("integer"); + Mplist = msymbol_as_managing_key ("plist"); + Mtext = msymbol_as_managing_key ("mtext"); + + for (i = 0; i < 256; i++) + hex_mnemonic[i] = 255; + for (i = '0'; i <= '9'; i++) + hex_mnemonic[i] = i - '0'; + for (i = 'A'; i <= 'F'; i++) + hex_mnemonic[i] = i - 'A' + 10; + for (i = 'a'; i <= 'f'; i++) + hex_mnemonic[i] = i - 'a' + 10; + for (i = 0; i < 256; i++) + escape_mnemonic[i] = i; + escape_mnemonic['e'] = 27; + escape_mnemonic['b'] = '\b'; + escape_mnemonic['f'] = '\f'; + escape_mnemonic['n'] = '\n'; + escape_mnemonic['r'] = '\r'; + escape_mnemonic['t'] = '\t'; + escape_mnemonic['\\'] = '\\'; + + return 0; +} + +void +mplist__fini (void) +{ +} + + +/* Parse this form of PLIST: + (symbol:KEY1 TYPE1:VAL1 symbol:KEY2 TYPE2:VAL2 ...) + and return a newly created plist of this form: + (KEY1:VAL1 KEY2:VAL2 ...) */ + +MPlist * +mplist__from_plist (MPlist *plist) +{ + MPlist *pl, *p; + + MPLIST_NEW (pl); + p = pl; + while (! MPLIST_TAIL_P (plist)) + { + MSymbol key, type; + + if (! MPLIST_SYMBOL_P (plist)) + MERROR (MERROR_PLIST, NULL); + key = MPLIST_SYMBOL (plist); + plist = MPLIST_NEXT (plist); + type = MPLIST_KEY (plist); + if (type->managing_key && MPLIST_VAL (plist)) + M17N_OBJECT_REF (MPLIST_VAL (plist)); + if (type == Mplist) + MPLIST_SET_NESTED_P (p); + MPLIST_SET_ADVANCE (p, key, MPLIST_VAL (plist)); + plist = MPLIST_NEXT (plist); + } + return pl; +} + +/** Parse this form of PLIST: + ((symbol:KEY1 ANY:VAL1 ... ) (symbol:KEY2 ANY:VAL2 ...) ...) + and return a newly created plist of this form: + (KEY1:(ANY:VAL1 ...) KEY2:(ANY:VAL2 ...) ...) + ANY can be any type. */ + +MPlist * +mplist__from_alist (MPlist *plist) +{ + MPlist *pl, *p; + + MPLIST_NEW (pl); + p = pl; + MPLIST_DO (plist, plist) + { + MPlist *elt; + + if (! MPLIST_PLIST_P (plist)) + MERROR (MERROR_PLIST, NULL); + elt = MPLIST_PLIST (plist); + if (! MPLIST_SYMBOL_P (elt)) + MERROR (MERROR_PLIST, NULL); + MPLIST_SET_NESTED_P (p); + MPLIST_SET_ADVANCE (p, MPLIST_SYMBOL (elt), MPLIST_NEXT (elt)); + M17N_OBJECT_REF (MPLIST_NEXT (elt)); + } + return pl; +} + + +MPlist * +mplist__from_file (FILE *fp, MPlist *keys) +{ + MPlist *plist, *pl; + MStream st; + + st.fp = fp; + st.eof = 0; + st.p = st.pend = st.buffer; + MPLIST_NEW (plist); + pl = plist; + while ((pl = read_element (pl, &st, keys))); + return plist; +} + + +/** Parse $STR of $N bytes and return a property list object. $FORMAT + must be either @c MTEXT_FORMAT_US_ASCII or @c MTEXT_FORMAT_UTF_8, + and controls how to produce @c STRING or @c M-TEXT in the + following definition. + + The syntax of $STR is as follows. + + PLIST ::= '(' ELEMENT * ')' + + ELEMENT ::= SYMBOL | INTEGER | UNSIGNED | STRING | M-TEXT | PLIST + + SYMBOL ::= ascii-character-sequence + + INTEGER ::= '-' ? [ '0' | .. | '9' ]+ + + UNSIGNED ::= '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ]+ + + M-TEXT ::= '"' byte-sequence '"' + + Each kind of @c ELEMENT is assigned one of these keys: + @c Msymbol, @c Mint, @c Munsigned, @c Mtext, @c Mplist + + In an ascii-character-sequence, a backslush (\) is used as the escape + character, which means that, for instance, "abc\ def" + produces a symbol whose name is of length seven with the fourth + character being a space. + + In a byte-sequence, "\r", "\n", "\e", and "\t" are replaced by CR, + NL, ESC, and TAB character respectively, "\xXX" are replaced by + byte 0xXX. After this replacement, the byte-sequence is decoded + into M-TEXT by $CODING. */ + +MPlist * +mplist__from_string (unsigned char *str, int n) +{ + MPlist *plist, *pl; + MStream st; + + st.fp = NULL; + st.eof = 0; + st.p = str; + st.pend = str + n; + MPLIST_NEW (plist); + pl = plist; + while ((pl = read_element (pl, &st, NULL))); + return plist; +} + +int +mplist__serialize (MText *mt, MPlist *plist, int pretty) +{ + MPlist *pl; + int separator = pretty ? '\n' : ' '; + + MPLIST_DO (pl, plist) + { + if (pl != plist) + mtext_cat_char (mt, separator); + write_element (mt, pl, pretty ? 0 : -1); + } + if (pretty) + mtext_cat_char (mt, separator); + return 0; +} + +/**en + @brief Concatenate two plists. + + The mplist__conc () function concatenates plist $TAIL at the end of + plist $PLIST and return $PLIST. If $TAIL is empty, return $PLIST + without modifying it. */ + +MPlist * +mplist__conc (MPlist *plist, MPlist *tail) +{ + MPlist *pl; + + if (MPLIST_TAIL_P (tail)) + return plist; + MPLIST_DO (pl, plist); + MPLIST_KEY (pl) = MPLIST_KEY (tail); + MPLIST_VAL (pl) = MPLIST_VAL (tail); + if (MPLIST_KEY (pl)->managing_key && MPLIST_VAL (pl)) + M17N_OBJECT_REF (MPLIST_VAL (pl)); + if (MPLIST_NESTED_P (tail)) + MPLIST_SET_NESTED_P (pl); + tail = MPLIST_NEXT (tail); + MPLIST_NEXT (pl) = tail; + M17N_OBJECT_REF (tail); + return plist; +} + +/*=*/ +/**en + @brief Discard a property at the beginning of a property list. + + The mplist__pop_unref () function removes a property at the + beginning of property list $PLIST, and if the property value is a + managed object, unref it. As a result, the second key and value + of the original $PLIST become the first of those of the new + $PLIST. */ + +void +mplist__pop_unref (MPlist *plist) +{ + MSymbol key; + void *val; + + if (MPLIST_TAIL_P (plist)) + return; + key = MPLIST_KEY (plist); + val = mplist_pop (plist); + if (key->managing_key) + M17N_OBJECT_UNREF (val); +} + +/**en + @brief Search for an element of an alist represented by a plist. + + The mplist__assq () function treats $PLIST as an association list + (elements are plists (key is #Mplist) whose first element is a + symbol (key is #Msymbol)), and find an element whose first element + has key #Msymbol and value $KEY. + + Non-plist elements of $PLIST are ignored. + + @return + This function returns a found element or NULL if no element + matches with $KEY. */ + +MPlist * +mplist__assq (MPlist *plist, MSymbol key) +{ + MPLIST_DO (plist, plist) + if (MPLIST_PLIST_P (plist)) + { + MPlist *pl = MPLIST_PLIST (plist); + + if (MPLIST_SYMBOL_P (pl) && MPLIST_SYMBOL (pl) == key) + return plist; + } + return NULL; +} + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/* External API */ + +/*** @addtogroup m17nPlist */ +/*** @{ */ +/*=*/ + +/***en + @brief Symbol whose name is "integer". + + The symbol @c Minteger has the name "integer". The value + of a property whose key is @c Minteger must be an integer. */ +/***ja + @brief "integer" ��̾���Ȥ��ƻ��ĥ���ܥ�. + + ����ܥ� @c Minteger �� "integer" �Ȥ���̾������ġ������� + @c Minteger �Ǥ���ץ��ѥƥ����ͤ������ͤǤʤ��ƤϤʤ�ʤ��� */ + +MSymbol Minteger; +/*=*/ + +/***en + @brief Symbol whose name is "plist". + + The symbol @c Mplist has the name "plist". It is a + managing key. A value of a property whose key is @c Mplist must + be a plist. */ +/***ja + @brief "plist" ��̾���Ȥ��ƻ��ĥ���ܥ�. + + ����ܥ� @c Mplist �� "plist" + �Ȥ���̾������ġ�����ϴ��������Ǥ��롣������ @c Mplist + �Ǥ���ץ��ѥƥ����ͤ� plist �Ǥʤ��ƤϤʤ�ʤ��� */ + +MSymbol Mplist; +/*=*/ + +/***en + @brief Symbol whose name is "mtext". + + The symbol @c Mtext has the name "mtext". It is a + managing key. A value of a property whose key is @c Mtext must be an + M-text. */ + +/***ja + @brief "mtext" ��̾���Ȥ��ƻ��ĥ���ܥ�. + + ����ܥ� @c Mtext �� "mtext" + �Ȥ���̾������Ĵ��������Ǥ��롣������ @c Mtext + �Ǥ���ץ��ѥƥ����ͤ� M-text �Ǥʤ��ƤϤʤ�ʤ��� */ + +MSymbol Mtext; + +/*=*/ +/***en + @brief Create a property list object. + + The mplist () function returns a newly created property list + object of length zero. + + @returns + This function returns a newly created property list. + + @errors + This function never fails. */ +/***ja + @brief �ץ��ѥƥ��ꥹ�ȥ��֥������Ȥ���. + + �ؿ� mplist () ��Ĺ�� 0 �Υץ��ѥƥ��ꥹ�ȥ��֥������Ȥ򿷤�����ä��֤��� + + @returns + ���δؿ��Ͽ��������줿�ץ��ѥƥ��ꥹ�ȥ��֥������Ȥ��֤��� + + @errors + ���δؿ��Ϸ褷�Ƽ��Ԥ��ʤ��� */ + +MPlist * +mplist (void) +{ + MPlist *plist; + + MPLIST_NEW (plist); + return plist; +} + +/*=*/ +/***en + @brief Copy a property list. + + The mplist_copy () function copies property list $PLIST. In the + copy, the values are the same as those of $PLIST. + + @return + This function returns a newly created plist which is a copy of + $PLIST. + + @errors + This function never fails. */ +/***ja + @brief �ץ��ѥƥ��ꥹ�Ȥ򥳥ԡ�����. + + �ؿ� mplist_copy () �ϥץ��ѥƥ��ꥹ�� $PLIST + �򥳥ԡ����롣���ԡ��Τ��٤Ƥ��ͤϥ��ԡ��� $PLIST ���ͤ�Ʊ���Ǥ��롣 + + @return + ���δؿ��Ͽ��������줿��$PLIST �Υ��ԡ��Ǥ���ץ��ѥƥ��ꥹ�Ȥ��֤��� + + @errors + ���δؿ��Ϸ褷�Ƽ��Ԥ��ʤ��� */ + +MPlist * +mplist_copy (MPlist *plist) +{ + MPlist *copy = mplist (), *pl = copy; + + MPLIST_DO (plist, plist) + { + if (MPLIST_NESTED_P (plist)) + MPLIST_SET_NESTED_P (pl); + pl = mplist_add (pl, MPLIST_KEY (plist), MPLIST_VAL (plist)); + } + return copy; +} + +/*=*/ + +/***en + @brief Set the value of a property in a property list. + + The mplist_put () function searches property list $PLIST + from the beginning for a property whose key is $KEY. If such a + property is found, its value is changed to $VALUE. Otherwise, a + new property whose key is $KEY and value is $VALUE is appended at + the end of $PLIST. See the documentation of mplist_add () for + the restriction on $KEY and $VAL. + + If $KEY is a managing key, $VAL must be a managed object. In this + case, the reference count of the old value, if not @c NULL, is + decremented by one, and that of $VAL is incremented by one. + + @return + If the operation was successful, mplist_put () returns a sublist of + $PLIST whose first element is the just modified or added one. + Otherwise, it returns @c NULL. */ +/***ja + @brief �ץ��ѥƥ��ꥹ����Υץ��ѥƥ����ͤ����ꤹ��. + + �ؿ� mplist_put () �ϥץ��ѥƥ��ꥹ�� $PLIST ��Ϥᤫ��õ���ơ������� + $KEY �Ǥ���ץ��ѥƥ��򸫤Ĥ��롣���Ĥ���С������ͤ� $VALUE + ���ѹ����롣���Ĥ���ʤ���С������� $KEY ���ͤ� $VALUE + �Ǥ��뿷�����ץ��ѥƥ��� $PLIST ���������ɲä���롣$KEY �� $VAL + ���Ф������¤ˤĤ��Ƥϡ�mplist_add () �������򻲾ȡ� + + $KEY �����������ʤ�С� + $VAL �ϴ��������֥������ȤǤʤ��ƤϤʤ�ʤ������ξ�硢�Ť��ͤλ��ȿ��� + @c NULL �Ǥʤ���� 1 ���餵�졢$VAL �λ��ȿ��� 1 ���䤵��롣 + + @return + ��������������� mplist_put () ���ѹ����줿���ɲä��줿���Ǥ���Ϥޤ� + $PLIST ����ʬ�ꥹ�Ȥ��֤��������Ǥʤ���� @c NULL ���֤��� */ + +MPlist * +mplist_put (MPlist *plist, MSymbol key, void *val) +{ + if (key == Mnil) + MERROR (MERROR_PLIST, NULL); + MPLIST_FIND (plist, key); + if (key->managing_key) + { + if (! MPLIST_TAIL_P (plist)) + M17N_OBJECT_UNREF (MPLIST_VAL (plist)); + if (val) + M17N_OBJECT_REF (val); + } + MPLIST_SET (plist, key, val); + return plist; +} + +/*=*/ + +/***en + @brief Get the value of a property in a property list. + + The mplist_get () function searches property list $PLIST from the + beginning for a property whose key is $KEY. If such a property is + found, its value is returned as the type of (void *). If + not found, @c NULL is returned. + + When @c NULL is returned, there are two possibilities: one is the + case where no property is found (see above); the other is the case + where a property is found and its value is @c NULL. In case that + these two cases must be distinguished, use the mplist_find_by_key () + function. */ +/***ja + @brief �ץ��ѥƥ��ꥹ����Υץ��ѥƥ����ͤ�����. + + �ؿ� mplist_get () �ϡ��ץ��ѥƥ��ꥹ�� $PLIST ��Ϥᤫ��õ���ơ����� + �� $KEY �Ǥ���ץ��ѥƥ��򸫤Ĥ��롣���Ĥ���С������ͤ� + (void *) �����֤������Ĥ���ʤ���� @c NULL ���֤��� + + @c NULL ���֤ä��ݤˤ���Ĥβ�ǽ��������: + �嵭�Τ褦�˥ץ��ѥƥ������Ĥ���ʤ��ä����ȡ��ץ��ѥƥ������Ĥ��ꡢ�����ͤ� + @c NULL �Ǥ�����Ǥ��롣��������̤���ɬ�פ�������ˤϴؿ� + mplist_find_by_key () ��Ȥ����ȡ� */ + +/*** + @seealso + mplist_find_by_key () */ + +void * +mplist_get (MPlist *plist, MSymbol key) +{ + MPLIST_FIND (plist, key); + return (MPLIST_TAIL_P (plist) ? NULL : MPLIST_VAL (plist)); +} + +/*=*/ + +/***en + @brief Set the value (function pointer) of a property in a property list. + + The mplist_put_func () function is similar to mplist_put () but for + setting function pointer $FUNC in property list $PLIST for key + $KEY. $KEY must not be a managing key. */ + +/***ja + @brief �ץ��ѥƥ��ꥹ����Υץ��ѥƥ��˴ؿ��ݥ��󥿤Ǥ����ͤ����ꤹ��. + + �ؿ� mplist_put_func () �ϴؿ� mplist_put () Ʊ�͡��ץ��ѥƥ��ꥹ�� $PLIST + ��ǥ����� $KEY �Ǥ���ץ��ѥƥ����ͤ����ꤹ�롣â�������ͤϴؿ��ݥ��� + $FUNC �Ǥ��롣$KEY �ϴ��������Ǥ��äƤϤʤ�ʤ��� */ + + +/*** + @seealso + mplist_put (), M17N_FUNC () */ + +MPlist * +mplist_put_func (MPlist *plist, MSymbol key, M17NFunc func) +{ + if (key == Mnil || key->managing_key) + MERROR (MERROR_PLIST, NULL); + MPLIST_FIND (plist, key); + MPLIST_KEY (plist) = key; + MPLIST_FUNC (plist) = func; + MPLIST_SET_VAL_FUNC_P (plist); + if (! plist->next) + MPLIST_NEW ((plist)->next); + return plist; +} + +/*=*/ + +/***en + @brief Get the value (function pointer) of a property in a property list. + + The mplist_get_func () function is similar to mplist_get () but for + getting a function pointer from property list $PLIST by key $KEY. */ + +/***ja + @brief �ץ��ѥƥ��ꥹ�Ȥ���ץ��ѥƥ��δؿ��ݥ��󥿤Ǥ����ͤ�����. + + �ؿ� mplist_get_func () �ϴؿ� mplist_get () ��Ʊ�ͤˡ��ץ��ѥƥ��� + ���� $PLIST ��ǥ����� $KEY �Ǥ���ץ��ѥƥ����͡�â���ؿ��ݥ��󥿡� + �����롣 */ + + +/*** + @seealso + mplist_get () */ +M17NFunc +mplist_get_func (MPlist *plist, MSymbol key) +{ + MPLIST_FIND (plist, key); + return (MPLIST_TAIL_P (plist) ? NULL : MPLIST_FUNC (plist)); +} + +/*=*/ + +/***en + @brief Add a property at the end of a property list. + + The mplist_add () function appends at the end of property list + $PLIST a property whose key is $KEY and value is $VAL. $KEY can + be any symbol other than @c Mnil. + + If $KEY is a managing key, $VAL must be a managed object. In this + case, the reference count of $VAL is incremented by one. + + @return + If the operation was successful, mplist_add () returns a sublist of + $PLIST whose first element is the just added one. Otherwise, it + returns @c NULL. */ +/***ja + @brief �ץ��ѥƥ��ꥹ�������˥ץ��ѥƥ����ɲä���. + + �ؿ� mplist_add () �ϡ��ץ��ѥƥ��ꥹ�� $PLIST �������˥����� $KEY + ���ͤ� $VAL �Ǥ���ץ��ѥƥ����ɲä��롣$KEY �ϡ�@c Mnil �ʳ���Ǥ�դΥ���ܥ�Ǥ褤�� + + $KEY �����������ʤ�С�$VAL �ϴ��������֥������ȤǤʤ��ƤϤʤ�ʤ������ξ�硢 + $VAL �λ��ȿ��� 1 ���䤵��롣 + + @return + ��������������� mplist_add () ���ɲä��줿���Ǥ���Ϥޤ� $PLIST + ����ʬ�ꥹ�Ȥ��֤��������Ǥʤ���� @c NULL ���֤��� */ + +MPlist * +mplist_add (MPlist *plist, MSymbol key, void *val) +{ + if (key == Mnil) + MERROR (MERROR_PLIST, NULL); + MPLIST_FIND (plist, Mnil); + if (val && key->managing_key) + M17N_OBJECT_REF (val); + MPLIST_KEY (plist) = key; + MPLIST_VAL (plist) = val; + MPLIST_NEW (plist->next); + return plist; +} + +/*=*/ + +/***en + @brief Add a property at the beginning of a property list. + + The mplist_push () function inserts at the beginning of property + list $PLIST a property whose key is $KEY and value is $VAL. + + If $KEY is a managing key, $VAL must be a managed object. In this + case, the reference count of $VAL is incremented by one. + + @return + If the operation was successful, this function returns $PLIST. + Otherwise, it returns @c NULL. */ +/***ja + @brief �ץ��ѥƥ��ꥹ�Ȥ���Ƭ�˥ץ��ѥƥ�����������. + + �ؿ� mplist_push () �ϥץ��ѥƥ��ꥹ�� $PLIST ����Ƭ�˥����� $KEY + ���ͤ� $VAL �Ǥ��륪�֥������Ȥ��������롣 + + $KEY �����������ʤ�С�$VAL �ϴ��������֥������ȤǤʤ��ƤϤʤ�ʤ������ξ�硢 + $VAL �λ��ȿ��� 1 ���䤵��롣 + + @return + ��������������Ф��δؿ��� $PLIST ���֤��������Ǥʤ����@c NULL + ���֤��� */ + +MPlist * +mplist_push (MPlist *plist, MSymbol key, void *val) +{ + MPlist *pl; + + if (key == Mnil) + MERROR (MERROR_PLIST, NULL); + MPLIST_NEW (pl); + MPLIST_KEY (pl) = MPLIST_KEY (plist); + MPLIST_VAL (pl) = MPLIST_VAL (plist); + if (MPLIST_NESTED_P (plist)) + MPLIST_SET_NESTED_P (pl); + MPLIST_NEXT (pl) = MPLIST_NEXT (plist); + plist->next = pl; + if (val && key->managing_key) + M17N_OBJECT_REF (val); + MPLIST_KEY (plist) = key; + MPLIST_VAL (plist) = val; + return plist; +} + +/*=*/ + +/***en + @brief Remove a property at the beginning of a property list. + + The mplist_pop () function removes a property at the beginning of + property list $PLIST. As a result, the second key and value of + the $PLIST become the first ones. + + @return + If the operation was successful, this function return the value of + the just popped property. Otherwise, it returns @c NULL. */ +/***ja + @brief �ץ��ѥƥ��ꥹ�Ȥ���Ƭ����ץ��ѥƥ���������. + + �ؿ� mplist_pop () �ϥץ��ѥƥ��ꥹ�� $PLIST ����Ƭ�Υץ��ѥƥ���� + �����롣��̤Ȥ��ơ�����2���ܤΥ������ͤ���Ƭ�Υ������ͤˤʤ롣 + + @return + ��������������С����δؿ��Ϻ�����줿�ץ��ѥƥ����ͤ��֤��������Ǥʤ���� + @c NULL ���֤��� */ + +void * +mplist_pop (MPlist *plist) +{ + void *val; + MPlist *next; + + if (MPLIST_TAIL_P (plist)) + return NULL; + val = MPLIST_VAL (plist); + next = MPLIST_NEXT (plist); + MPLIST_KEY (plist) = MPLIST_KEY (next); + MPLIST_VAL (plist) = MPLIST_VAL (next); + if (MPLIST_KEY (plist) != Mnil + && MPLIST_KEY (plist)->managing_key + && MPLIST_VAL (plist)) + M17N_OBJECT_REF (MPLIST_VAL (plist)); + MPLIST_NEXT (plist) = MPLIST_NEXT (next); + if (plist->next) + M17N_OBJECT_REF (plist->next); + M17N_OBJECT_UNREF (next); + return val; +} + +/*=*/ +/***en + @brief Find a property of a specific key in a property list. + + The mplist_find_by_key () function searches property list + $PLIST from the beginning for a property whose key is $KEY. If + such a property is found, a sublist of $PLIST whose first element + is the found one is returned. Otherwise, @c NULL is returned. + + If $KEY is @c Mnil, it returns a sublist of $PLIST whose + first element is the last one of $PLIST. */ +/***ja + @brief �ץ��ѥƥ��ꥹ���椫�����Υ�������ĥץ��ѥƥ���õ��. + + �ؿ� mplist_find_by_key () �ϥץ��ѥƥ��ꥹ�� $PLIST + ��Ϥᤫ��õ ���ơ������� $KEY + �Ǥ���ץ��ѥƥ��򸫤Ĥ��롣���Ĥ���С����Υץ��ѥƥ�����Ϥޤ� + $PLIST ����ʬ�ꥹ�Ȥ��֤��������Ǥʤ���� @c NULL ���֤��� + + $KEY �� @c Mnil �ʤ�С�$PLIST �κǸ�����Ǥ���Ϥޤ���ʬ�ꥹ�Ȥ��֤��� */ + +MPlist * +mplist_find_by_key (MPlist *plist, MSymbol key) +{ + MPLIST_FIND (plist, key); + return (MPLIST_TAIL_P (plist) + ? (key == Mnil ? plist : NULL) + : plist); +} + +/*=*/ +/***en + @brief Find a property of a specific value in a property list. + + The mplist_find_by_value () function searches property list $PLIST + from the beginning for a property whose value is $VAL. If such a + property is found, a sublist of $PLIST whose first element is the + found one is returned. Otherwise, @c NULL is returned. */ +/***ja + @brief �ץ��ѥƥ��ꥹ���椫�������ͤ���ĥץ��ѥƥ���õ��. + + �ؿ� mplist_find_by_value () �ϥץ��ѥƥ��ꥹ�� $PLIST + ��Ϥᤫ��õ���ơ��ͤ� $VAL + �Ǥ���ץ��ѥƥ��򸫤Ĥ��롣���Ĥ���С����Υץ��ѥƥ�����Ϥޤ� + $PLIST ����ʬ�ꥹ�Ȥ��֤��������Ǥʤ���� @c NULL ���֤��� */ + +MPlist * +mplist_find_by_value (MPlist *plist, void *val) +{ + MPLIST_DO (plist, plist) + { + if (MPLIST_VAL (plist) == val) + return plist; + } + return NULL; +} + +/*=*/ + +/***en + @brief Return the next sublist of a property list. + + The mplist_next () function returns a pointer to the sublist of + property list $PLIST, which begins at the second element in $PLIST. If the + length of $PLIST is zero, it returns @c NULL. */ +/***ja + @brief �ץ��ѥƥ��ꥹ�Ȥμ�����ʬ�ꥹ�Ȥ��֤�. + + �ؿ� mplist_next () �ϥץ��ѥƥ��ꥹ�� $PLIST �� 2 + ���ܤ����Ǥ���Ϥޤ���ʬ�ꥹ�ȤؤΥݥ��󥿤��֤���$PLIST ��Ĺ���� 0 + �ʤ�� @c NULL ���֤��� */ + +MPlist * +mplist_next (MPlist *plist) +{ + return (MPLIST_TAIL_P (plist) ? NULL : plist->next); +} + +/*=*/ + +/***en + @brief Set the first property in a property list. + + The mplist_set () function sets the key and the value of the first + property in property list $PLIST to $KEY and $VALUE, respectively. + See the documentation of mplist_add () for the restriction on $KEY + and $VAL. + + @return + If the operation was successful, mplist_set () returns $PLIST. + Otherwise, it returns @c NULL. */ +/***ja + @brief �ץ��ѥƥ��ꥹ�Ȥκǽ�Υץ��ѥƥ������ꤹ��. + + �ؿ� mplist_set () �ϥץ��ѥƥ��ꥹ�� $PLIST + �κǽ�Υץ��ѥƥ��Υ������ͤ򤽤줾�� $KEY �� $VALUE �����ꤹ�롣 + $KEY �� $VAL ���Ф������¤ˤĤ��Ƥϡ�mplist_add () �������򻲾ȡ� + + @return + ��������������� mplist_set () �� $PLIST ���֤��������Ǥʤ���� @c NULL ���֤��� */ + +MPlist * +mplist_set (MPlist *plist, MSymbol key, void * val) +{ + if (key == Mnil) + { + if (! MPLIST_TAIL_P (plist)) + { + key = MPLIST_KEY (plist); + M17N_OBJECT_UNREF (MPLIST_NEXT (plist)); + MPLIST_KEY (plist) = Mnil; + if (key->managing_key) + M17N_OBJECT_UNREF (MPLIST_VAL (plist)); + plist->next = NULL; + } + } + else + { + if (val && key->managing_key) + M17N_OBJECT_REF (val); + if (! MPLIST_TAIL_P (plist) + && MPLIST_KEY (plist)->managing_key) + M17N_OBJECT_UNREF (MPLIST_VAL (plist)); + MPLIST_SET (plist, key, val); + } + return plist; +} + +/*=*/ + +/***en + @brief Return the length of a property list. + + The mplist_length () function returns the number of properties in + property list $PLIST. */ +/***ja + @brief �ץ��ѥƥ��ꥹ�Ȥ�Ĺ�����֤�. + + �ؿ� mplist_length () �ϥץ��ѥƥ��ꥹ�� $PLIST ��Υץ��ѥƥ��ο����֤��� */ + +int +mplist_length (MPlist *plist) +{ + int n; + + for (n = 0; ! (MPLIST_TAIL_P (plist)); n++, plist = plist->next); + return n; +} + +/*=*/ + +/***en + @brief Return the key of the first property in a property list. + + The mplist_key () function returns the key of the first property + in property list $PLIST. If the length of $PLIST is zero, + it returns @c Mnil. */ +/***ja + @brief �ץ��ѥƥ��ꥹ����κǽ�Υץ��ѥƥ��Υ������֤�. + + �ؿ� mplist_key () �ϡ��ץ��ѥƥ��ꥹ�� $PLIST + ��κǽ�Υץ��ѥƥ��Υ������֤���$PLIST ��Ĺ���� 0 �ʤ�С� @c Mnil + ���֤��� */ + +MSymbol +mplist_key (MPlist *plist) +{ + return MPLIST_KEY (plist); +} + +/*=*/ + +/***en + @brief Return the value of the first property in a property list. + + The mplist_value () function returns the value of the first + property in property list $PLIST. If the length of $PLIST + is zero, it returns @c NULL. */ +/***ja + @brief �ץ��ѥƥ��ꥹ����κǽ�Υץ��ѥƥ����ͤ��֤�. + + �ؿ� mplist_value () �ϡ��ץ��ѥƥ��ꥹ�� $PLIST ��κǽ�Υץ��ѥƥ����ͤ��֤��� + $PLIST ��Ĺ���� 0 �ʤ�С� @c Mnil ���֤��� */ + +void * +mplist_value (MPlist *plist) +{ + return MPLIST_VAL (plist); +} + +/***en + @brief Generate a property list by deserializing an M-text. + + The mplist_deserialize () function parses M-text $MT and returns a + property list. + + The syntax of $MT is as follows. + + MT ::= '(' ELEMENT * ')' + + ELEMENT ::= SYMBOL | INTEGER | M-TEXT | PLIST + + SYMBOL ::= ascii-character-sequence + + INTEGER ::= '-' ? [ '0' | .. | '9' ]+ + | '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ]+ + + M-TEXT ::= '"' character-sequence '"' + + Each alternatives of @c ELEMENT is assigned one of these keys: @c + Msymbol, @c Minteger, @c Mtext, @c Mplist + + In an ascii-character-sequence, a backslash (\) is used as the escape + character, which means that, for instance, abc\ def + produces a symbol whose name is of length seven with the fourth + character being a space. */ +/***ja + @brief M-text ��ǥ��ꥢ�饤�����ƥץ��ѥƥ��ꥹ�Ȥ���. + + �ؿ� mplist_deserialize () �� M-text $MT ����Ϥ��ƥץ��ѥƥ��ꥹ�Ȥ��֤��� + + $MT �Υ��󥿥å����ϰʲ����̤ꡣ + + MT ::= '(' ELEMENT * ')' + + ELEMENT ::= SYMBOL | INTEGER | M-TEXT | PLIST + + SYMBOL ::= ��������ʸ���� + + INTEGER ::= '-' ? [ '0' | .. | '9' ]+ + | '0x' [ '0' | .. | '9' | 'A' | .. | 'F' | 'a' | .. | 'f' ]+ + + M-TEXT ::= '"' character-sequence '"' + + @c ELEMENT �γ������ϥ�����@c Msymbol, @c Minteger, @c Mtext, + @c Mplist �Τ����줫�������Ƥ��Ƥ��롣 + + ��������ʸ������Ǥϡ��Хå�����å��� (\) ������������ʸ���Ȥ����Ѥ����롣���Ȥ��� + abc\ def �� 4 ʸ���ܤ�����ʸ���Ǥ���Ĺ���� 7 + �Ǥ������̾������ĥ���ܥ���������롣 */ + +MPlist * +mplist_deserialize (MText *mt) +{ + MPlist *plist; + MText *tmp = NULL; + + if (mt->format > MTEXT_FORMAT_UTF_8) + { + if (MTEXT_READ_ONLY_P (mt)) + mt = tmp = mtext_cpy (mtext (), mt); + else + mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8); + } + plist = mplist__from_string (MTEXT_DATA (mt), mtext_nbytes (mt)); + if (tmp) + M17N_OBJECT_UNREF (tmp); + return plist; +} + +/*** @} */ + +/*** @addtogroup m17nDebug */ +/*=*/ +/*** @{ */ + +/***en + @brief Dump a property list. + + The mdebug_dump_plist () function prints a property list $PLIST in + a human readable way to the stderr or to what specified by the + environment variable MDEBUG_OUTPUT_FILE. $INDENT specifies how + many columns to indent the lines but the first one. + + @return + This function returns $PLIST. */ +/***ja + @brief �ץ��ѥƥ��ꥹ�Ȥ����פ���. + + �ؿ� mdebug_dump_plist () �ϥץ��ѥƥ��ꥹ�� $PLIST ��ɸ�२�顼�� + �Ϥ⤷���ϴĶ��ѿ� MDEBUG_DUMP_FONT �ǻ��ꤵ�줿�ե�����˿ʹ֤˲� + �ɤʷ��ǰ������롣 $INDENT �ϣ����ܰʹߤΥ���ǥ�Ȥ���ꤹ�롣 + + @return + ���δؿ��� $PLIST ���֤��� */ +MPlist * +mdebug_dump_plist (MPlist *plist, int indent) +{ + char *prefix = (char *) alloca (indent + 1); + MPlist *pl; + + memset (prefix, 32, indent); + prefix[indent] = 0; + + fprintf (mdebug__output, "("); + MPLIST_DO (pl, plist) + { + if (pl != plist) + fprintf (mdebug__output, "\n%s ", prefix); + write_element (NULL, pl, indent + 1); + } + fprintf (mdebug__output, ")"); + return plist; +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/plist.h b/src/plist.h new file mode 100644 index 0000000..5e7b6f1 --- /dev/null +++ b/src/plist.h @@ -0,0 +1,120 @@ +/* plist.h -- header file for the plist module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_PLIST_H_ +#define _M17N_PLIST_H_ + +struct MPlist +{ + /** Header for a managed object. */ + M17NObject control; + + /**en Key of the first element of the plist. If the value is Mnil, + this is the tail of the plist. In that case, and is + NULL. If the value is a managing key, is a managed + object. */ + MSymbol key; + + /**en Value of the first element of the plist. */ + union { + void *pointer; + M17NFunc func; + } val; + + /**en Plist for the next element. */ + MPlist *next; +}; + +/** Macros to access each member of PLIST. */ + +#define MPLIST_KEY(plist) ((plist)->key) +#define MPLIST_VAL(plist) ((plist)->val.pointer) +#define MPLIST_FUNC(plist) ((plist)->val.func) +#define MPLIST_NEXT(plist) ((plist)->next) +#define MPLIST_TAIL_P(plist) ((plist)->key == Mnil) + +#define MPLIST_SYMBOL_P(plist) (MPLIST_KEY (plist) == Msymbol) +#define MPLIST_STRING_P(plist) (MPLIST_KEY (plist) == Mstring) +#define MPLIST_MTEXT_P(plist) (MPLIST_KEY (plist) == Mtext) +#define MPLIST_INTEGER_P(plist) (MPLIST_KEY (plist) == Minteger) +#define MPLIST_PLIST_P(plist) (MPLIST_KEY (plist) == Mplist) + +#define MPLIST_NESTED_P(plist) \ + ((plist)->control.flag & 1) +#define MPLIST_SET_NESTED_P(plist) \ + ((plist)->control.flag |= 1) + +#define MPLIST_VAL_FUNC_P(plist) \ + ((plist)->control.flag & 2) +#define MPLIST_SET_VAL_FUNC_P(plist) \ + ((plist)->control.flag |= 2) + +#define MPLIST_SYMBOL(plist) ((MSymbol) MPLIST_VAL (plist)) +#define MPLIST_STRING(plist) ((char *) MPLIST_VAL (plist)) +#define MPLIST_MTEXT(plist) ((MText *) MPLIST_VAL (plist)) +#define MPLIST_INTEGER(plist) ((int) MPLIST_VAL (plist)) +#define MPLIST_PLIST(plist) ((MPlist *) MPLIST_VAL (plist)) + +#define MPLIST_FIND(plist, key) \ + do { \ + while (! MPLIST_TAIL_P (plist) && MPLIST_KEY (plist) != (key)) \ + (plist) = (plist)->next; \ + } while (0) + + +#define MPLIST_DO(elt, plist) \ + for ((elt) = (plist); ! MPLIST_TAIL_P (elt); (elt) = MPLIST_NEXT (elt)) + +#define MPLIST_LENGTH(plist) \ + (MPLIST_TAIL_P (plist) ? 0 \ + : MPLIST_TAIL_P ((plist)->next) ? 1 \ + : MPLIST_TAIL_P ((plist)->next->next) ? 2 \ + : mplist_length (plist)) + +#define MPLIST_ADD_PLIST(PLIST, KEY, VAL) \ + MPLIST_SET_NESTED_P (mplist_add ((PLIST), (KEY), (VAL))) +#define MPLIST_PUSH_PLIST(PLIST, KEY, VAL) \ + MPLIST_SET_NESTED_P (mplist_push ((PLIST), (KEY), (VAL))) +#define MPLIST_PUT_PLIST(PLIST, KEY, VAL) \ + MPLIST_SET_NESTED_P (mplist_put ((PLIST), (KEY), (VAL))) + + +extern unsigned char hex_mnemonic[256]; +extern unsigned char escape_mnemonic[256]; + +extern MPlist *mplist__from_file (FILE *fp, MPlist *keys); + +extern MPlist *mplist__from_plist (MPlist *plist); + +extern MPlist *mplist__from_alist (MPlist *plist); + +extern MPlist *mplist__from_string (unsigned char *str, int n); + +extern int mplist__serialize (MText *mt, MPlist *plist, int pretty); + +extern MPlist *mplist__conc (MPlist *plist, MPlist *tail); + +extern void mplist__pop_unref (MPlist *plist); + +extern MPlist *mplist__assq (MPlist *plist, MSymbol key); + +#endif /* _M17N_PLIST_H_ */ diff --git a/src/symbol.c b/src/symbol.c new file mode 100644 index 0000000..78396d9 --- /dev/null +++ b/src/symbol.c @@ -0,0 +1,848 @@ +/* symbol.c -- symbol module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nSymbol + + @brief Symbol objects and API for them. + + The m17n library uses objects called @e symbols as unambiguous + identifiers. Symbols are similar to atoms in the X library, but a + symbol can have zero or more @e symbol @e properties. A symbol + property consists of a @e key and a @e value, where key is also a + symbol and value is anything that can be cast to (void *). + "The symbol property that belongs to the symbol S and + whose key is K" may be shortened to "K property of S". + + Symbols are used mainly in the following three ways. + + @li As keys of symbol properties and other properties. + + @li To represent various objects, e.g. charsets, coding systems, + fontsets. + + @li As arguments of the m17n library functions to control + their behavior. + + There is a special kind of symbol, a @e managing @e key. The + value of a property whose key is a managing key must be a @e + managed @e object. See @ref m17nObject for the detail. +*/ +/***ja + @addtogroup m17nSymbol ����ܥ� + + @brief ����ܥ륪�֥������ȤȤ���˴ؤ��� API. + + m17n �饤�֥��ϰ�դ˷�ޤ뼱�̻ҤȤ��� @e ����ܥ� + �ȸƤ֥��֥������Ȥ��Ѥ��롣����ܥ�� X �饤�֥��Υ��ȥ�Ȼ��Ƥ��뤬�� + 0 �İʾ�� @e ����ܥ�ץ��ѥƥ� ����Ĥ��Ȥ��Ǥ��롣����ܥ�ץ��ѥƥ��� + @e ���� �� @e �� ����ʤ롣�����Ϥ��켫�Υ���ܥ�Ǥ��ꡢ�ͤ� + (void *) ���˥��㥹�ȤǤ����Τʤ鲿�Ǥ�褤���֥���ܥ� + S �����ĥ���ܥ�ץ��ѥƥ��Τ��������� K �Τ�Ρפ��ñ�ˡ�S �� K + �ץ��ѥƥ��פȸƤ֤��Ȥ����롣 + + ����ܥ�����Ӥϼ�˰ʲ���3�̤�Ǥ��롣 + + @li ����ܥ�ץ��ѥƥ������¾�Υץ��ѥƥ��Υ�����ɽ���� + + @li ʸ�����åȡ������ɷϡ��ե���ȥ��åȤʤɤγƼ索�֥������Ȥ�ɽ���� + + @li m17n �饤�֥��ؿ��ΰ����Ȥʤꡢ�ؿ��ε�ư�����椹�롣 + + @e �������� �ȸƤФ�����̤ʥ���ܥ뤬���ꡢ���������򥭡��Ȥ��ƻ��ĥץ��ѥƥ����ͤ� + @e ���������֥������� �Ǥʤ��ƤϤʤ�ʤ����ܺ٤� @ref m17nObject ���ȡ� +*/ + +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include +#include + +#include "m17n.h" +#include "m17n-misc.h" +#include "internal.h" +#include "symbol.h" +#include "character.h" +#include "mtext.h" +#include "plist.h" + +static int num_symbols; + +#define SYMBOL_TABLE_SIZE 1024 + +static MSymbol symbol_table[SYMBOL_TABLE_SIZE]; + +static unsigned +hash_string (const char *str, int len) +{ + unsigned hash = 0; + const char *end = str + len; + unsigned c; + + while (str < end) + { + c = *((unsigned char *) str++); + if (c >= 0140) + c -= 40; + hash = ((hash << 3) + (hash >> 28) + c); + } + return hash & (SYMBOL_TABLE_SIZE - 1); +} + + +static MPlist * +serialize_symbol (void *val) +{ + MPlist *plist = mplist (); + + mplist_add (plist, Msymbol, val); + return plist; +} + +static void * +deserialize_symbol (MPlist *plist) +{ + return (MPLIST_SYMBOL_P (plist) ? MPLIST_SYMBOL (plist) : Mnil); +} + + +/* Internal API */ + +int +msymbol__init () +{ + num_symbols = 0; + Mnil = (MSymbol) 0; + Mt = msymbol ("t"); + Msymbol = msymbol ("symbol"); + Mstring = msymbol ("string"); + return 0; +} + +void +msymbol__fini () +{ + int i; + MSymbol sym; + + for (i = 0; i < SYMBOL_TABLE_SIZE; i++) + for (sym = symbol_table[i]; sym; sym = sym->next) + if (! MPLIST_TAIL_P (&sym->plist)) + { + if (sym->plist.key->managing_key) + M17N_OBJECT_UNREF (MPLIST_VAL (&sym->plist)); + M17N_OBJECT_UNREF (sym->plist.next); + sym->plist.key = Mnil; + } +} + +void +msymbol__free_table () +{ + int i; + MSymbol sym, next; + int freed_symbols = 0; + + for (i = 0; i < SYMBOL_TABLE_SIZE; i++) + { + for (sym = symbol_table[i]; sym; sym = next) + { + next = sym->next; + free (sym->name); + free (sym); + freed_symbols++; + } + symbol_table[i] = NULL; + } + if (mdebug__flags[MDEBUG_FINI]) + fprintf (mdebug__output, "%16s %7d %7d %7d\n", "Symbol", + num_symbols, freed_symbols, num_symbols - freed_symbols); + num_symbols = 0; +} + + +MSymbol +msymbol__with_len (const char *name, int len) +{ + char *p = alloca (len + 1); + + memcpy (p, name, len); + p[len] = '\0'; + return msymbol (p); +} + +/** Return a plist of symbols that has non-NULL property PROP. If + PROP is Mnil, return a plist of all symbols. Values of the plist + is NULL. */ + +MPlist * +msymbol__list (MSymbol prop) +{ + MPlist *plist = mplist (); + int i; + MSymbol sym; + + for (i = 0; i < SYMBOL_TABLE_SIZE; i++) + for (sym = symbol_table[i]; sym; sym = sym->next) + if (prop == Mnil || msymbol_get (sym, prop)) + mplist_push (plist, sym, NULL); + return plist; +} + + +/** Canonicalize the name of SYM, and return a symbol of the + canonicalized name. Canonicalization is done by this rule: + o convert all uppercase characters to lowercase. + o remove all non alpha-numeric characters. + o change the leading "ibm" to "cp". + o change the leading "windows-" to "cp". + o change the leading "cp" to "ibm". + o remove the leading "iso". + For instance: + "ISO-8859-2" -> "88592" + "euc-JP" -> "eucjp" + "IBM851" -> "cp851" + "windows-1250" -> "cp250" + + This function is used to canonicalize charset and coding system + names. */ + +MSymbol +msymbol__canonicalize (MSymbol sym) +{ + char *name = sym->name; + /* Extra 2 bytes are for changing "cpXXX" to "ibmXXX" and + terminating '\0'. */ + char *canon = (char *) alloca (strlen (name) + 2); + char *p = canon; + + for (; *name; name++) + if (ISALNUM (*name)) + *p++ = TOLOWER (*name); + *p = '\0'; + if (p - canon > 3 && canon[0] == 'i') + { + if (canon[1] == 'b' && canon[2] == 'm' && isdigit (canon[3])) + { + /* Change "ibmXXX" to "cpXXX". */ + canon++; + canon[0] = 'c'; + canon[1] = 'p'; + } + else if (canon[1] == 's' && canon[2] == 'o') + { + /* Change "isoXXX" to "XXX". */ + canon += 3; + } + } + else if (p - canon > 2 + && canon[0] == 'c' && canon[1] == 'p' && isdigit (canon[2])) + { + /* Change "cpXXX" to "ibmXXX". */ + for (; p >= canon + 2; p--) + p[1] = p[0]; + canon[0] = 'i'; + canon[1] = 'b'; + canon[2] = 'm'; + } + else if (canon[0] == 'w' && p - canon > 7 + && memcmp (canon + 1, "indows", 6) == 0 + && isdigit (canon[7])) + { + /* Change "windowsXXX" to "cpXXX" */ + canon += 5; + canon[0] = 'c'; + canon[1] = 'p'; + } + return msymbol (canon); +} + +MTextPropSerializeFunc msymbol__serializer = serialize_symbol; +MTextPropDeserializeFunc msymbol__deserializer = deserialize_symbol; + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/* External API */ + +/*** @addtogroup m17nSymbol */ +/*** @{ */ + +/*=*/ +/***en + @brief Symbol whose name is "nil". + + The symbol #Mnil has the name "nil" and, in general, + represents @e false or @e no. When coerced to "int", its value is + zero. #Mnil can't have any symbol property. */ +/***ja + @brief "nil" ��̾���Ȥ��ƻ��ĥ���ܥ�. + + ����ܥ� #Mnil �� "nil" + �Ȥ���̾������������̤ˡֵ��פޤ��ϡ�����פ��̣���롣 + "int" ���Ѵ����줿��硢�ͤ� 0 �Ǥ��롣 + #Mnil ���ȤϤ����ʤ륷��ܥ�ץ��ѥƥ�������ʤ��� */ + +MSymbol Mnil; + +/*=*/ + +/***en + @brief Symbol whose name is "t". + + The symbol #Mt has the name "t" and, in general, + represents @e true or @e yes. */ +/***ja + @brief "t" ��̾���Ȥ��ƻ��ĥ���ܥ�. + + ����ܥ� #Mt �� "t" �Ȥ���̾������������̤ˡֿ��פޤ��ϡֹ���פ��̣���롣 */ + +MSymbol Mt; + +/*=*/ + +/***en + @brief Symbol whose name is "string". + + The symbol #Mstring has the name "string" and is used + as an argument of the functions mchar_define_property (), + etc. */ +/***ja + @brief "string" ��̾���Ȥ��ƻ��ĥ���ܥ�. + + ����ܥ� #Mstring �� "string" �Ȥ���̾����������ؿ� + mchar_define_property () �ʤɤΰ����Ȥ����Ѥ����롣 */ + +MSymbol Mstring; + +/*=*/ + +/***en + @brief Symbol whose name is "symbol". + + The symbol #Msymbol has the name "symbol" and is used + as an argument of the functions mchar_define_property (), + etc. */ +/***ja + @brief "symbol" ��̾���Ȥ��ƻ��ĥ���ܥ�. + + ����Ѥߥ���ܥ� #Msymbol �� "symbol" �Ȥ���̾����������ؿ� + mchar_define_property () �ʤɤΰ����Ȥ��ƻȤ��롣 */ + +MSymbol Msymbol; + +/*=*/ + +/***en + @brief Get a symbol. + + The msymbol () function returns the canonical symbol whose name is + $NAME. If there is none, one is created. The created one is not + a managing key. + + Symbols whose name starts by two spaces are reserved by the m17n + library, and are used by the library only internally. + + @return + This function returns the found or created symbol. + + @errors + This function never fails. */ +/***ja + @brief ����ܥ������. + + �ؿ� msymbol () �� $NAME + �Ȥ���̾����������������줿����ܥ���֤������Τ褦�ʥ���ܥ뤬¸�ߤ��ʤ����ˤϡ��������롣�������줿����ܥ�ϴ��������ǤϤʤ��� + + ����ʸ����ĤǻϤޤ륷��ܥ�� m17n �饤�֥���ѤǤ��ꡢ����Ū�ˤΤ��Ѥ����롣 + + @return + ���δؿ��ϸ��Ĥ�����������������������ܥ���֤��� + + @errors + ���δؿ��Ϸ褷�Ƽ��Ԥ��ʤ��� + + @latexonly \IPAlabel{msymbol} @endlatexonly */ + +/*** + @seealso + msymbol_as_managing_key (), msymbol_name (), msymbol_exist () */ + +MSymbol +msymbol (const char *name) +{ + MSymbol sym; + int len; + unsigned hash; + + len = strlen (name); + if (len == 3 && name[0] == 'n' && name[1] == 'i' && name[2] == 'l') + return Mnil; + hash = hash_string (name, len); + len++; + for (sym = symbol_table[hash]; sym; sym = sym->next) + if (len == sym->length + && *name == *(sym->name) + && ! memcmp (name, sym->name, len)) + return sym; + + num_symbols++; + MTABLE_CALLOC (sym, 1, MERROR_SYMBOL); + MTABLE_MALLOC (sym->name, len, MERROR_SYMBOL); + memcpy (sym->name, name, len); + sym->length = len; + sym->next = symbol_table[hash]; + symbol_table[hash] = sym; + return sym; +} + +/***en + @brief Create a managing key. + + The msymbol_as_managing_key () function returns a newly created + managing key whose name is $NAME. It there already exists a + symbol of name $NAME, it returns #Mnil. + + Symbols whose name starts by two spaces are reserved by the m17n + library, and are used by the library only internally. + + @return + If the operation was successful, this function returns the created + symbol. Otherwise, it returns #Mnil. */ +/***ja + @brief ������������. + + �ؿ� msymbol_as_managing_key () ��̾�� $NAME + ����Ŀ��������줿�����������֤������Ǥ�̾�� $NAME ����ĥ���ܥ뤬����С� + #Mnil ���֤��� + + ����ʸ����ĤǻϤޤ륷��ܥ�� m17n �饤�֥���ѤǤ��ꡢ����Ū�ˤΤ��Ѥ����롣 + + @return + ��������������С����δؿ���������������ܥ���֤��������Ǥʤ���� + #Mnil ���֤��� */ + +/*** + @errors + MERROR_SYMBOL + + @seealso + msymbol (), msymbol_exist () */ + +MSymbol +msymbol_as_managing_key (const char *name) +{ + MSymbol sym; + int len; + unsigned hash; + + len = strlen (name); + if (len == 3 && name[0] == 'n' && name[1] == 'i' && name[2] == 'l') + MERROR (MERROR_SYMBOL, Mnil); + hash = hash_string (name, len); + len++; + for (sym = symbol_table[hash]; sym; sym = sym->next) + if (len == sym->length + && *name == *(sym->name) + && ! memcmp (name, sym->name, len)) + MERROR (MERROR_SYMBOL, Mnil); + + num_symbols++; + MTABLE_CALLOC (sym, 1, MERROR_SYMBOL); + sym->managing_key = 1; + MTABLE_MALLOC (sym->name, len, MERROR_SYMBOL); + memcpy (sym->name, name, len); + sym->length = len; + sym->next = symbol_table[hash]; + symbol_table[hash] = sym; + return sym; +} + +/*=*/ + +/***en + @brief Check if a symbol is a managing key. + + The msymbol_is_managing_key () function checks if the symbol + $SYMBOL is a managing key or not. + + @return + Return 1 if the symbol is a managing key. Otherwise, + return 0. */ + +int +msymbol_is_managing_key (MSymbol symbol) +{ + return (symbol->managing_key == 1); +} + +/*=*/ + +/***en + @brief Search for a symbol that has a specified name. + + The msymbol_exist () function searches for the symbol whose name + is $NAME. + + @return + If such a symbol exists, msymbol_exist () returns that symbol. + Otherwise it returns the predefined symbol #Mnil. + + @errors + This function never fails. */ +/***ja + @brief ���ꤵ�줿̾������ĥ���ܥ��õ��. + + �ؿ� msymbol_exist () �� $NAME �Ȥ���̾������ĥ���ܥ��õ���� + + @return + �⤷���Τ褦�ʥ���ܥ뤬¸�ߤ���ʤ�Ф��Υ���ܥ���֤��������Ǥʤ���С�����Ѥߥ���ܥ� + #Mnil ���֤��� + + @errors + ���δؿ��Ϸ褷�Ƽ��Ԥ��ʤ��� */ + +/***@seealso + msymbol_name (), msymbol () */ + +MSymbol +msymbol_exist (const char *name) +{ + MSymbol sym; + int len; + unsigned hash; + + len = strlen (name); + if (len == 3 && name[0] == 'n' && name[1] == 'i' && name[2] == 'l') + return Mnil; + hash = hash_string (name, len); + len++; + for (sym = symbol_table[hash]; sym; sym = sym->next) + if (len == sym->length + && *name == *(sym->name) + && ! memcmp (name, sym->name, len)) + return sym; + return Mnil; +} + +/*=*/ + +/***en + @brief Get symbol name. + + The msymbol_name () function returns a pointer to a string + containing the name of $SYMBOL. + + @errors + This function never fails. */ +/***ja + @brief ����ܥ��̾��������. + + �ؿ� msymbol_name () �ϻ��ꤵ�줿����ܥ� $SYMBOL + ��̾����ޤ�ʸ����ؤΥݥ��󥿤��֤��� + + @errors + ���δؿ��Ϸ褷�Ƽ��Ԥ��ʤ��� */ + +/***@seealso + msymbol (), msymbol_exist () */ + +char * +msymbol_name (MSymbol symbol) +{ + return (symbol == Mnil ? "nil" : symbol->name); +} + +/*=*/ +/***en + @brief Set the value of a symbol property. + + The msymbol_put () function assigns $VAL to the value of the + symbol property that belongs to $SYMBOL and whose key is $KEY. If + the symbol property already has a value, $VAL overwrites the old + one. Both $SYMBOL and $KEY must not be #Mnil. + + If $KEY is a managing key, $VAL must be a managed object. In this + case, the reference count of the old value, if not @c NULL, is + decremented by one, and that of $VAL is incremented by one. + + @return + If the operation was successful, msymbol_put () returns 0. + Otherwise it returns -1 and assigns an error code to the external + variable #merror_code. */ +/***ja + @brief ����ܥ�ץ��ѥƥ����ͤ����ꤹ��. + + �ؿ� msymbol_put () �ϡ�����ܥ� $SYMBOL ��ǥ����� $KEY �Ǥ��륷��ܥ�ץ��ѥƥ����ͤ� + $VAL �����ꤹ�롣���Υ���ܥ�ץ��ѥƥ��ˤ��Ǥ��ͤ�����о�񤭤��롣 + $SYMBOL, $KEY �Ȥ� #Mnil �Ǥ��äƤϤʤ�ʤ��� + + $KEY �����������ʤ�С�$VAL �ϴ��������֥������ȤǤʤ��ƤϤʤ�ʤ������ξ�硢�Ť��ͤλ��ȿ��� + @c NULL �Ǥʤ���� 1 ���餵�졢$VAL �λ��ȿ��� 1 ���䤵��롣 + + @return + ��������������С�msymbol_put () �� 0 ���֤��������Ǥʤ���� -1 + ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_SYMBOL + + @seealso + msymbol_get () */ + +int +msymbol_put (MSymbol symbol, MSymbol key, void *val) +{ + if (symbol == Mnil || key == Mnil) + MERROR (MERROR_SYMBOL, -1); + mplist_put (&symbol->plist, key, val); + return 0; +} + +/*=*/ + +/***en + @brief Get the value of a symbol property. + + The msymbol_get () function searches for the value of the symbol + property that belongs to $SYMBOL and whose key is $KEY. If + $SYMBOL has such a symbol property, its value is returned. + Otherwise @c NULL is returned. + + @return + If an error is detected, msymbol_get () returns @c NULL and + assigns an error code to the external variable #merror_code. */ +/***ja + @brief ����ܥ�ץ��ѥƥ����ͤ�����. + + �ؿ� msymbol_get () �ϡ�����ܥ� $SYMBOL + �����ĥ���ܥ�ץ��ѥƥ��Τ����������� $KEY + �Ǥ����Τ�õ�����⤷�������륷��ܥ�ץ��ѥƥ���¸�ߤ���С�������ͤ��֤��������Ǥʤ���� + @c NULL ���֤��� + + @return + ���顼�����Ф��줿��硢msymbol_get () �� @c NULL + ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +/*** + @errors + @c MERROR_SYMBOL + + @seealso + msymbol_put () */ + +void * +msymbol_get (MSymbol symbol, MSymbol key) +{ + MPlist *plist; + + if (symbol == Mnil || key == Mnil) + return NULL; + plist = &symbol->plist; + MPLIST_FIND (plist, key); + return (MPLIST_TAIL_P (plist) ? NULL : MPLIST_VAL (plist)); +} + +/*=*/ +/***en + @brief Set the value (function pointer) of a symbol property. + + The msymbol_put_func () function is similar to msymbol_put () but for + setting function pointer $FUNC as the property value of $SYMBOL for + key $KEY. */ + +/***ja + @brief ����ܥ�ץ��ѥƥ�����(�ؿ��ݥ���)�����ꤹ��. + + �ؿ� msymbol_put_func () �ϡ��ؿ� msymbol_put () ��Ʊ�ͤˡ�����ܥ� + $SYMBOL �Υ����� $KEY �Ǥ��륷��ܥ�ץ��ѥƥ����ͤ����ꤹ�롣â�� + �����ͤϴؿ��ݥ��� $FUNC �Ǥ��롣 */ + +/*** + @seealso + msymbol_put (), M17N_FUNC () */ +int +msymbol_put_func (MSymbol symbol, MSymbol key, M17NFunc func) +{ + if (symbol == Mnil || key == Mnil) + MERROR (MERROR_SYMBOL, -1); + mplist_put_func (&symbol->plist, key, func); + return 0; +} + +/*=*/ + +/***en + @brief Get the value (function pointer) of a symbol property. + + The msymbol_get_func () function is similar to msymbol_get () but for + getting a function pointer form the property of symbol $SYMBOL. */ + +/***ja + @brief ����ܥ�ץ��ѥƥ����� (�ؿ��ݥ���) ������. + + �ؿ� msymbol_get_func () �ϡ��ؿ� msymbol_get () ��Ʊ�ͤˡ�����ܥ� + $SYMBOL �����ĥ���ܥ�ץ��ѥƥ��Τ����������� $KEY �Ǥ����Τ����롣â�� + �����ͤϴؿ��ݥ��󥿤�Ǥ��롣 */ + +/*** + @seealso + msymbol_get () */ + +M17NFunc +msymbol_get_func (MSymbol symbol, MSymbol key) +{ + if (symbol == Mnil || key == Mnil) + return NULL; + return mplist_get_func (&symbol->plist, key); +} + +/*** @} */ + +#include + +/*** @addtogroup m17nDebug */ +/*=*/ +/*** @{ */ + +/***en + @brief Dump a symbol. + + The mdebug_dump_symbol () function prints symbol $SYMBOL in a + human readable way to the stderr or to what specified by the + environment variable MDEBUG_OUTPUT_FILE. $INDENT specifies how + many columns to indent the lines but the first one. + + @return + This function returns $SYMBOL. + + @errors + MERROR_DEBUG */ +/***ja + @brief ����ܥ�����פ���. + + �ؿ� mdebug_dump_symbol () �ϥ���ܥ� $symbol ��ɸ�२�顼���Ϥ⤷ + ���ϴĶ��ѿ� MDEBUG_DUMP_FONT �ǻ��ꤵ�줿�ե�����˿ʹ֤˲��ɤʷ� + �ǰ������롣 $INDENT �ϣ����ܰʹߤΥ���ǥ�Ȥ���ꤹ�롣 + + @return + ���δؿ��� $SYMBOL ���֤��� + + @errors + MERROR_DEBUG */ + +MSymbol +mdebug_dump_symbol (MSymbol symbol, int indent) +{ + char *prefix; + MPlist *plist; + char *name; + + if (indent < 0) + MERROR (MERROR_DEBUG, Mnil); + prefix = (char *) alloca (indent + 1); + memset (prefix, 32, indent); + prefix[indent] = 0; + + if (symbol == Mnil) + plist = NULL, name = "nil"; + else + plist = &symbol->plist, name = symbol->name; + + fprintf (mdebug__output, "%s%s", prefix, name); + while (plist && MPLIST_KEY (plist) != Mnil) + { + fprintf (mdebug__output, ":%s", MPLIST_KEY (plist)->name); + plist = MPLIST_NEXT (plist); + } + return symbol; +} + +/***en + @brief Dump all symbol names. + + The mdebug_dump_all_symbols () function prints names of all + symbols to the stderr or to what specified by the environment + variable MDEBUG_OUTPUT_FILE. $INDENT specifies how many columns + to indent the lines but the first one. + + @return + This function returns #Mnil. + + @errors + MERROR_DEBUG */ +/***ja + @brief ���٤ƤΥ���ܥ�̾�����פ���. + + �ؿ� mdebug_dump_all_symbols () �ϡ����٤ƤΥ���ܥ��̾����ɸ�२ + �顼���Ϥ⤷���ϴĶ��ѿ� MDEBUG_DUMP_FONT �ǻ��ꤵ�줿�ե�����˰� + �����롣 $INDENT �ϣ����ܰʹߤΥ���ǥ�Ȥ���ꤹ�롣 + + @return + ���δؿ��� #Mnil ���֤��� + + @errors + MERROR_DEBUG */ + + +MSymbol +mdebug_dump_all_symbols (int indent) +{ + char *prefix; + int i, n; + MSymbol sym; + + if (indent < 0) + MERROR (MERROR_DEBUG, Mnil); + prefix = (char *) alloca (indent + 1); + memset (prefix, 32, indent); + prefix[indent] = 0; + + fprintf (mdebug__output, "(symbol-list"); + for (i = n = 0; i < SYMBOL_TABLE_SIZE; i++) + if ((sym = symbol_table[i])) + { + fprintf (mdebug__output, "\n%s (%4d", prefix, i); + for (; sym; sym = sym->next, n++) + fprintf (mdebug__output, " '%s'", sym->name); + fprintf (mdebug__output, ")"); + } + fprintf (mdebug__output, "\n%s (total %d)", prefix, n); + fprintf (mdebug__output, ")"); + return Mnil; +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/symbol.h b/src/symbol.h new file mode 100644 index 0000000..3925c68 --- /dev/null +++ b/src/symbol.h @@ -0,0 +1,60 @@ +/* symbol.h -- header file for the symbol module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_SYMBOL_H_ +#define _M17N_SYMBOL_H_ + +#include "plist.h" + +struct MSymbolStruct +{ + /** 1 iff a value of property (including text-property) whose key is + the symbol is a managed object. */ + unsigned managing_key : 1; + + /* Name of the symbol. */ + char *name; + + /* Byte length of . */ + int length; + + /* Plist of the symbol. */ + MPlist plist; + + struct MSymbolStruct *next; +}; + +#define MSYMBOL_NAME(sym) ((sym)->name) +#define MSYMBOL_NAMELEN(sym) ((sym)->length - 1) + +extern void msymbol__free_table (); + +extern MSymbol msymbol__with_len (const char *name, int len); + +extern MPlist *msymbol__list (MSymbol prop); + +extern MSymbol msymbol__canonicalize (MSymbol sym); + +extern MTextPropSerializeFunc msymbol__serializer; +extern MTextPropDeserializeFunc msymbol__deserializer; + +#endif /* _M17N_SYMBOL_H_ */ diff --git a/src/textprop.c b/src/textprop.c new file mode 100644 index 0000000..2e67890 --- /dev/null +++ b/src/textprop.c @@ -0,0 +1,3112 @@ +/* textprop.c -- text property module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +/***en + @addtogroup m17nTextProperty + @brief Function to handle text properties. + + Each character in an M-text can have properties called @e text @e + properties. Text properties store various kinds of information + attached to parts of an M-text to provide application programs + with a unified view of those information. As rich information can + be stored in M-texts in the form of text properties, functions in + application programs can be simple. + + A text property consists of a @e key and @e values, where key is a + symbol and values are anything that can be cast to (void *) + . Unlike other types of properties, a text property can + have multiple values. "The text property whose key is K" may be + shortened to "K property". */ + +/***ja + @addtogroup m17nTextProperty + @brief �ƥ����ȥץ��ѥƥ������뤿��δؿ�. + + M-text ��γ�ʸ���ϡ�@e �ƥ����ȥץ��ѥƥ� �ȸƤФ��ץ��ѥƥ��� + ���Ĥ��Ȥ��Ǥ��롣�ƥ����ȥץ��ѥƥ��ϡ�M-text �γ����̤��ղä��� + �����ޤ��ޤʾ�����ݻ����Ƥ��ꡢ���ץꥱ�������ץ������Ϥ���� + �ξ��������Ū�˰������Ȥ��Ǥ��롣M-text ���Τ�˭�٤ʾ������Ĥ� + �ᡢ���ץꥱ�������ץ��������δؿ�����Dz����뤳�Ȥ��Ǥ��롣 + + �ƥ����ȥץ��ѥƥ��� @e ���� �� @e �� ����ʤ롣�����ϥ���ܥ�Ǥ� + �ꡢ�ͤ� (void *) ���˥��㥹�ȤǤ����Τʤ鲿�Ǥ�褤�� + ¾�Υ����פΥץ��ѥƥ��Ȱۤʤꡢ��ĤΥƥ����ȥץ��ѥƥ���ʣ������ + ����Ĥ��Ȥ�������롣�֥����� K �Ǥ���ƥ����ȥץ��ѥƥ��פΤ��� + ���ñ�ˡ�K �ץ��ѥƥ��פȸƤ֤��Ȥ����롣 */ + +/*=*/ + +#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE) +/*** @addtogroup m17nInternal + @{ */ + +#include +#include +#include +#include + +#ifdef HAVE_XML2 +#include +#include +#include +#include +#endif + +#include "m17n.h" +#include "m17n-misc.h" +#include "internal.h" +#include "symbol.h" +#include "mtext.h" +#include "textprop.h" + +#define TEXT_PROP_DEBUG + +#undef xassert +#ifdef TEXT_PROP_DEBUG +#define xassert(X) do {if (!(X)) mdebug_hook ();} while (0) +#else +#define xassert(X) (void) 0 +#endif /* not FONTSET_DEBUG */ + +/* Hierarchy of objects (MText, MTextPlist, MInterval, MTextProperty) + +MText + | key/a key/b key/x + +--> MTextPlist -> MTextPlist -> ... -> MTextPlist + | | + | +- tail <-----------------------------------------+ + | | | + | +- head <--> MInterval <--> ... <--> MInterval <--+ + | + +- tail --------------------------------------------------------+ + | | + +- head --> MInterval <--> MInterval <--> ... <--> MInterval <--+ + | | + +---------------+------------> MTextProperty + +--> MTextProperty + ... + + +Examples: + +MTextProperty a/A [AAAAAAAAAAAAAAAAAAAAA] +MTextProperty a/B [BBBBBBBBBBBBBBBBB] +MTextPlist a |--intvl1--|-intvl2-|-intvl3-|---intvl4---|-intvl5-| + + +MTextProperty b/A [AAAAAAAAAA] +MTextProperty b/B [BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB] +MTextPlist b |-intvl1-|--intvl2--|--intvl3--|-intvl4-|--intvl5--| + + M-text |--------------------------------------------------| + + (intvl == MInterval) + +*/ + +/* The structure MTextProperty is defined in textprop.h. */ + +/** MInterval is the structure for an interval that holds text + properties of the same key in a specific range of M-text. + All intervals are stored in MIntervalPool. */ + +typedef struct MInterval MInterval; + +struct MInterval +{ + /** Stack of pointers to text properties. If the interval does not + have any text properties, this member is NULL or contains random + values. */ + MTextProperty **stack; + + /** How many values are in . */ + int nprops; + + /** Length of . */ + int stack_length; + + /** Start and end character positions of the interval. If is + negative, this interval is not in use. */ + int start, end; + + /** Pointers to the previous and next intervals. If is 0, + is NULL and this interval is pointed by MTextPlist->head. + If is the size of the M-text, is NULL, and this + interval is pointed by MTextPlist->tail. */ + MInterval *prev, *next; +}; + +/** MTextPlist is a structure to hold text properties of an M-text by + chain. Each element in the chain is for a specific key. */ + +typedef struct MTextPlist MTextPlist; + +struct MTextPlist +{ + /** Key of the property. */ + MSymbol key; + + /** The head and tail intervals. ->start is always 0. + end is always MText->nchars. */ + MInterval *head, *tail; + + /** Lastly accessed interval. */ + MInterval *cache; + + /* Not yet implemented. */ + int (*modification_hook) (MText *mt, MSymbol key, int from, int to); + + /** Pointer to the next property in the chain, or NULL if the + property is the last one in the chain. */ + MTextPlist *next; +}; + + +/** How many intervals one interval-pool can contain. */ + +#define INTERVAL_POOL_SIZE 1024 + +typedef struct MIntervalPool MIntervalPool; + + +/** MIntervalPool is the structure for an interval-pool which store + intervals. Each interval-pool contains INTERVAL_POOL_SIZE number + of intervals, and is chained from the root #interval_pool. */ + +struct MIntervalPool +{ + /** Array of intervals. */ + MInterval intervals[INTERVAL_POOL_SIZE]; + + /** The smallest index to an unused interval. */ + int free_slot; + + /** Pointer to the next interval-pool. */ + MIntervalPool *next; +}; + + +/** Root of interval-pools. */ + +static MIntervalPool interval_pool_root; + +/* For debugging. */ + +static M17NObjectArray text_property_table; + +/** Return a newly allocated interval pool. */ + +static MIntervalPool * +new_interval_pool () +{ + MIntervalPool *pool; + int i; + + MSTRUCT_CALLOC (pool, MERROR_TEXTPROP); + for (i = 0; i < INTERVAL_POOL_SIZE; i++) + pool->intervals[i].end = -1; + pool->free_slot = 0; + pool->next = NULL; + return pool; +} + + +/** Return a new interval for the region START and END. */ + +static MInterval * +new_interval (int start, int end) +{ + MIntervalPool *pool; + MInterval *interval; + + for (pool = &interval_pool_root; + pool->free_slot >= INTERVAL_POOL_SIZE; + pool = pool->next) + { + if (! pool->next) + pool->next = new_interval_pool (); + } + + interval = &(pool->intervals[pool->free_slot]); + interval->stack = NULL; + interval->nprops = 0; + interval->stack_length = 0; + interval->prev = interval->next = NULL; + interval->start = start; + interval->end = end; + + pool->free_slot++; + while (pool->free_slot < INTERVAL_POOL_SIZE + && pool->intervals[pool->free_slot].end >= 0) + pool->free_slot++; + + return interval; +} + + +/** Free INTERVAL and return INTERVAL->next. It assumes that INTERVAL + has no properties. */ + +static MInterval * +free_interval (MInterval *interval) +{ + MIntervalPool *pool = &interval_pool_root; + int i; + + xassert (interval->nprops == 0); + if (interval->stack) + free (interval->stack); + while ((interval < pool->intervals + || interval >= pool->intervals + INTERVAL_POOL_SIZE) + && pool->next) + pool = pool->next; + + i = interval - pool->intervals; + interval->end = -1; + if (i < pool->free_slot) + pool->free_slot = i; + return interval->next; +} + + +/** If necessary, allocate a stack for INTERVAL so that it can contain + NUM number of text properties. */ + +#define PREPARE_INTERVAL_STACK(interval, num) \ + do { \ + if ((num) > (interval)->stack_length) \ + { \ + MTABLE_REALLOC ((interval)->stack, (num), MERROR_TEXTPROP); \ + (interval)->stack_length = (num); \ + } \ + } while (0) + + +/** Return a copy of INTERVAL. The copy still shares text properties + with INTERVAL. If MASK_BITS is not zero, don't copy such text + properties whose control flags contains bits in MASK_BITS. */ + +static MInterval * +copy_interval (MInterval *interval, int mask_bits) +{ + MInterval *new = new_interval (interval->start, interval->end); + int nprops = interval->nprops; + MTextProperty **props = alloca (sizeof (MTextProperty *) * nprops); + int i, n; + + for (i = n = 0; i < nprops; i++) + if (! (interval->stack[i]->control.flag & mask_bits)) + props[n++] = interval->stack[i]; + new->nprops = n; + if (n > 0) + { + PREPARE_INTERVAL_STACK (new, n); + memcpy (new->stack, props, sizeof (MTextProperty *) * n); + } + + return new; +} + + +/** Free text property OBJECT. */ + +static void +free_text_property (void *object) +{ + MTextProperty *prop = (MTextProperty *) object; + + if (prop->key->managing_key) + M17N_OBJECT_UNREF (prop->val); + M17N_OBJECT_UNREGISTER (text_property_table, prop); + free (object); +} + + +/** Return a newly allocated text property whose key is KEY and value + is VAL. */ + +static MTextProperty * +new_text_property (MText *mt, int from, int to, MSymbol key, void *val, + int control_bits) +{ + MTextProperty *prop; + + M17N_OBJECT (prop, free_text_property, MERROR_TEXTPROP); + prop->control.flag = control_bits; + prop->attach_count = 0; + prop->mt = mt; + prop->start = from; + prop->end = to; + prop->key = key; + prop->val = val; + if (key->managing_key) + M17N_OBJECT_REF (val); + M17N_OBJECT_REGISTER (text_property_table, prop); + return prop; +} + + +/** Return a newly allocated copy of text property PROP. */ + +#define COPY_TEXT_PROPERTY(prop) \ + new_text_property ((prop)->mt, (prop)->start, (prop)->end, \ + (prop)->key, (prop)->val, (prop)->control.flag) + + +/** Split text property PROP at position INTERVAL->start, and make all + the following intervals contain the copy of PROP instead of PROP. + It assumes that PROP starts before INTERVAL. */ + +static void +split_property (MTextProperty *prop, MInterval *interval) +{ + int end = prop->end; + MTextProperty *copy; + int i; + + prop->end = interval->start; + copy = COPY_TEXT_PROPERTY (prop); + copy->start = interval->start; + copy->end = end; + /* Check all stacks of the following intervals, and if it contains + PROP, change it to the copy of it. */ + for (; interval && interval->start < end; interval = interval->next) + for (i = 0; i < interval->nprops; i++) + if (interval->stack[i] == prop) + { + interval->stack[i] = copy; + M17N_OBJECT_REF (copy); + copy->attach_count++; + prop->attach_count--; + M17N_OBJECT_UNREF (prop); + } + M17N_OBJECT_UNREF (copy); +} + +/** Divide INTERVAL of PLIST at POS if POS is in between the range of + INTERVAL. */ + +static void +divide_interval (MTextPlist *plist, MInterval *interval, int pos) +{ + MInterval *new; + int i; + + if (pos == interval->start || pos == interval->end) + return; + new = copy_interval (interval, 0); + interval->end = new->start = pos; + new->prev = interval; + new->next = interval->next; + interval->next = new; + if (new->next) + new->next->prev = new; + if (plist->tail == interval) + plist->tail = new; + for (i = 0; i < new->nprops; i++) + { + new->stack[i]->attach_count++; + M17N_OBJECT_REF (new->stack[i]); + } +} + + +/** Check if INTERVAL of PLIST can be merged with INTERVAL->next. If + mergeable, extend INTERVAL to the end of INTEVAL->next, free + INTERVAL->next, and return INTERVAL. Otherwise, return + INTERVAL->next. */ + +static MInterval * +maybe_merge_interval (MTextPlist *plist, MInterval *interval) +{ + int nprops = interval->nprops; + MInterval *next = interval->next; + int i, j; + + if (! next || nprops != next->nprops) + return next; + + for (i = 0; i < nprops; i++) + { + MTextProperty *prop = interval->stack[i]; + MTextProperty *old = next->stack[i]; + + if (prop != old + && (prop->val != old->val + || prop->end != old->start + || prop->control.flag & MTEXTPROP_NO_MERGE + || old->control.flag & MTEXTPROP_NO_MERGE)) + return interval->next; + } + + + for (i = 0; i < nprops; i++) + { + MTextProperty *prop = interval->stack[i]; + MTextProperty *old = next->stack[i]; + + if (prop != old) + { + MInterval *tail; + + for (tail = next->next; tail && tail->start < old->end; + tail = tail->next) + for (j = 0; j < tail->nprops; j++) + if (tail->stack[j] == old) + { + old->attach_count--; + xassert (old->attach_count); + tail->stack[j] = prop; + prop->attach_count++; + M17N_OBJECT_REF (prop); + } + xassert (old->attach_count == 1); + old->mt = NULL; + prop->end = old->end; + } + old->attach_count--; + M17N_OBJECT_UNREF (old); + } + + interval->end = next->end; + interval->next = next->next; + if (next->next) + next->next->prev = interval; + if (plist->tail == next) + plist->tail = interval; + plist->cache = interval; + next->nprops = 0; + free_interval (next); + return interval; +} + + +/** Adjust start and end positions of intervals between HEAD and TAIL + (both inclusive) by diff. Adjust also start and end positions + of text properties belonging to those intervals. */ + +static void +adjust_intervals (MInterval *head, MInterval *tail, int diff) +{ + int i; + MTextProperty *prop; + + if (diff < 0) + { + /* Adjust end positions of properties starting before HEAD. */ + for (i = 0; i < head->nprops; i++) + { + prop = head->stack[i]; + if (prop->start < head->start) + prop->end += diff; + } + + /* Adjust start and end positions of properties starting at + HEAD, and adjust HEAD itself. */ + while (1) + { + for (i = 0; i < head->nprops; i++) + { + prop = head->stack[i]; + if (prop->start == head->start) + prop->start += diff, prop->end += diff; + } + head->start += diff; + head->end += diff; + if (head == tail) + break; + head = head->next; + } + } + else + { + /* Adjust start poistions of properties ending after TAIL. */ + for (i = 0; i < tail->nprops; i++) + { + prop = tail->stack[i]; + if (prop->end > tail->end) + prop->start += diff; + } + + /* Adjust start and end positions of properties ending at + TAIL, and adjust TAIL itself. */ + while (1) + { + for (i = 0; i < tail->nprops; i++) + { + prop = tail->stack[i]; + if (prop->end == tail->end) + prop->start += diff, prop->end += diff; + } + tail->start += diff; + tail->end += diff; + if (tail == head) + break; + tail = tail->prev; + } + } +} + +/* Return an interval of PLIST that covers the position POS. */ + +static MInterval * +find_interval (MTextPlist *plist, int pos) +{ + MInterval *interval; + MInterval *highest; + + if (pos < plist->head->end) + return plist->head; + if (pos >= plist->tail->start) + return (pos < plist->tail->end ? plist->tail : NULL); + + interval = plist->cache; + + if (pos < interval->start) + highest = interval->prev, interval = plist->head->next; + else if (pos < interval->end) + return interval; + else + highest = plist->tail->prev, interval = interval->next; + + if (pos - interval->start < highest->end - pos) + { + while (interval->end <= pos) + /* Here, we are sure that POS is not included in PLIST->tail, + thus, INTERVAL->next always points a valid next + interval. */ + interval = interval->next; + } + else + { + while (highest->start > pos) + highest = highest->prev; + interval = highest; + } + plist->cache = interval; + return interval; +} + +/* Push text property PROP on the stack of INTERVAL. */ + +#define PUSH_PROP(interval, prop) \ + do { \ + int n = (interval)->nprops; \ + \ + PREPARE_INTERVAL_STACK ((interval), n + 1); \ + (interval)->stack[n] = (prop); \ + (interval)->nprops += 1; \ + (prop)->attach_count++; \ + M17N_OBJECT_REF (prop); \ + if ((prop)->start > (interval)->start) \ + (prop)->start = (interval)->start; \ + if ((prop)->end < (interval)->end) \ + (prop)->end = (interval)->end; \ + } while (0) + + +/* Pop the topmost text property of INTERVAL from the stack. If it + ends after INTERVAL->end, split it. */ + +#define POP_PROP(interval) \ + do { \ + MTextProperty *prop; \ + \ + (interval)->nprops--; \ + prop = (interval)->stack[(interval)->nprops]; \ + xassert (prop->control.ref_count > 0); \ + xassert (prop->attach_count > 0); \ + if (prop->start < (interval)->start) \ + { \ + if (prop->end > (interval)->end) \ + split_property (prop, (interval)->next); \ + prop->end = (interval)->start; \ + } \ + else if (prop->end > (interval)->end) \ + prop->start = (interval)->end; \ + prop->attach_count--; \ + if (! prop->attach_count) \ + prop->mt = NULL; \ + M17N_OBJECT_UNREF (prop); \ + } while (0) + + +#define REMOVE_PROP(interval, prop) \ + do { \ + int i; \ + \ + for (i = (interval)->nprops - 1; i >= 0; i--) \ + if ((interval)->stack[i] == (prop)) \ + break; \ + if (i < 0) \ + break; \ + (interval)->nprops--; \ + for (; i < (interval)->nprops; i++) \ + (interval)->stack[i] = (interval)->stack[i + 1]; \ + (prop)->attach_count--; \ + if (! (prop)->attach_count) \ + (prop)->mt = NULL; \ + M17N_OBJECT_UNREF (prop); \ + } while (0) + + +#ifdef TEXT_PROP_DEBUG +static int +check_plist (MTextPlist *plist, int start) +{ + MInterval *interval = plist->head; + MInterval *cache = plist->cache; + int cache_found = 0; + + if (interval->start != start + || interval->start >= interval->end) + return mdebug_hook (); + while (interval) + { + int i; + + if (interval == interval->next) + return mdebug_hook (); + + if (interval == cache) + cache_found = 1; + + if (interval->start >= interval->end) + return mdebug_hook (); + if ((interval->next + ? (interval->end != interval->next->start + || interval != interval->next->prev) + : interval != plist->tail)) + return mdebug_hook (); + for (i = 0; i < interval->nprops; i++) + { + if (interval->stack[i]->start > interval->start + || interval->stack[i]->end < interval->end) + return mdebug_hook (); + + if (! interval->stack[i]->attach_count) + return mdebug_hook (); + if (! interval->stack[i]->mt) + return mdebug_hook (); + if (interval->stack[i]->start == interval->start) + { + MTextProperty *prop = interval->stack[i]; + int count = prop->attach_count - 1; + MInterval *interval2; + + for (interval2 = interval->next; + interval2 && interval2->start < prop->end; + count--, interval2 = interval2->next) + if (count == 0) + return mdebug_hook (); + } + + if (interval->stack[i]->end > interval->end) + { + MTextProperty *prop = interval->stack[i]; + MInterval *interval2; + int j; + + for (interval2 = interval->next; + interval2 && interval2->start < prop->end; + interval2 = interval2->next) + { + for (j = 0; j < interval2->nprops; j++) + if (interval2->stack[j] == prop) + break; + if (j == interval2->nprops) + return mdebug_hook (); + } + } + if (interval->stack[i]->start < interval->start) + { + MTextProperty *prop = interval->stack[i]; + MInterval *interval2; + int j; + + for (interval2 = interval->prev; + interval2 && interval2->end > prop->start; + interval2 = interval2->prev) + { + for (j = 0; j < interval2->nprops; j++) + if (interval2->stack[j] == prop) + break; + if (j == interval2->nprops) + return mdebug_hook (); + } + } + } + interval = interval->next; + } + if (! cache_found) + return mdebug_hook (); + if (plist->head->prev || plist->tail->next) + return mdebug_hook (); + return 0; +} +#endif + + +/** Return a copy of plist that contains intervals between FROM and TO + of PLIST. The copy goes to the position POS of M-text MT. */ + +static MTextPlist * +copy_single_property (MTextPlist *plist, int from, int to, MText *mt, int pos) +{ + MTextPlist *new; + MInterval *interval1, *interval2; + MTextProperty *prop; + int diff = pos - from; + int i, j; + int mask_bits = MTEXTPROP_VOLATILE_STRONG | MTEXTPROP_VOLATILE_WEAK; + + MSTRUCT_CALLOC (new, MERROR_TEXTPROP); + new->key = plist->key; + new->next = NULL; + + interval1 = find_interval (plist, from); + new->head = copy_interval (interval1, mask_bits); + for (interval1 = interval1->next, interval2 = new->head; + interval1 && interval1->start < to; + interval1 = interval1->next, interval2 = interval2->next) + { + interval2->next = copy_interval (interval1, mask_bits); + interval2->next->prev = interval2; + } + new->tail = interval2; + new->head->start = from; + new->tail->end = to; + for (interval1 = new->head; interval1; interval1 = interval1->next) + for (i = 0; i < interval1->nprops; i++) + if (interval1->start == interval1->stack[i]->start + || interval1 == new->head) + { + prop = interval1->stack[i]; + interval1->stack[i] = COPY_TEXT_PROPERTY (prop); + interval1->stack[i]->mt = mt; + interval1->stack[i]->attach_count++; + if (interval1->stack[i]->start < from) + interval1->stack[i]->start = from; + if (interval1->stack[i]->end > to) + interval1->stack[i]->end = to; + for (interval2 = interval1->next; interval2; + interval2 = interval2->next) + for (j = 0; j < interval2->nprops; j++) + if (interval2->stack[j] == prop) + { + interval2->stack[j] = interval1->stack[i]; + interval1->stack[i]->attach_count++; + M17N_OBJECT_REF (interval1->stack[i]); + } + } + adjust_intervals (new->head, new->tail, diff); + new->cache = new->head; + for (interval1 = new->head; interval1 && interval1->next; + interval1 = maybe_merge_interval (new, interval1)); + xassert (check_plist (new, pos) == 0); + if (new->head == new->tail + && new->head->nprops == 0) + { + free_interval (new->head); + free (new); + new = NULL; + } + + return new; +} + +/** Return a newly allocated plist whose key is KEY on M-text MT. */ + +static MTextPlist * +new_plist (MText *mt, MSymbol key) +{ + MTextPlist *plist; + + MSTRUCT_MALLOC (plist, MERROR_TEXTPROP); + plist->key = key; + plist->head = new_interval (0, mtext_nchars (mt)); + plist->tail = plist->head; + plist->cache = plist->head; + plist->next = mt->plist; + mt->plist = plist; + return plist; +} + +/* Free PLIST and return PLIST->next. */ + +static MTextPlist * +free_textplist (MTextPlist *plist) +{ + MTextPlist *next = plist->next; + MInterval *interval = plist->head; + + while (interval) + { + while (interval->nprops > 0) + POP_PROP (interval); + interval = free_interval (interval); + } + free (plist); + return next; +} + +/** Return a plist that contains the property KEY of M-text MT. If + such a plist does not exist and CREATE is nonzero, create a new + plist and return it. */ + +static MTextPlist * +get_plist_create (MText *mt, MSymbol key, int create) +{ + MTextPlist *plist; + + plist = mt->plist; + while (plist && plist->key != key) + plist = plist->next; + + /* If MT does not have PROP, make one. */ + if (! plist && create) + plist = new_plist (mt, key); + return plist; +} + +/* Detach PROP. INTERVAL (if not NULL) contains PROP. */ + +static void +detach_property (MTextPlist *plist, MTextProperty *prop, MInterval *interval) +{ + MInterval *head; + int to = prop->end; + + xassert (prop->mt); + xassert (plist); + + M17N_OBJECT_REF (prop); + if (interval) + while (interval->start > prop->start) + interval = interval->prev; + else + interval = find_interval (plist, prop->start); + head = interval; + while (1) + { + REMOVE_PROP (interval, prop); + if (interval->end == to) + break; + interval = interval->next; + } + xassert (prop->attach_count == 0 && prop->mt == NULL); + M17N_OBJECT_UNREF (prop); + + while (head && head->end <= to) + head = maybe_merge_interval (plist, head); + xassert (check_plist (plist, 0) == 0); +} + +/* Delete text properties of PLIST between FROM and TO. MASK_BITS + specifies what kind of properties to delete. If DELETING is + nonzero, delete such properties too that are completely included in + the region. + + If the resulting PLIST still has any text properties, return 1, + else return 0. */ + +static int +delete_properties (MTextPlist *plist, int from, int to, + int mask_bits, int deleting) +{ + MInterval *interval; + int modified = 0; + int modified_from = from; + int modified_to = to; + int i; + + retry: + for (interval = find_interval (plist, from); + interval && interval->start < to; + interval = interval->next) + for (i = 0; i < interval->nprops; i++) + { + MTextProperty *prop = interval->stack[i]; + + if (prop->control.flag & mask_bits) + { + if (prop->start < modified_from) + modified_from = prop->start; + if (prop->end > modified_to) + modified_to = prop->end; + detach_property (plist, prop, interval); + modified++; + goto retry; + } + else if (deleting && prop->start >= from && prop->end <= to) + { + detach_property (plist, prop, interval); + modified++; + goto retry; + } + } + + if (modified) + { + interval = find_interval (plist, modified_from); + while (interval && interval->start < modified_to) + interval = maybe_merge_interval (plist, interval); + } + + return (plist->head != plist->tail || plist->head->nprops > 0); +} + +static void +pop_interval_properties (MInterval *interval) +{ + while (interval->nprops > 0) + POP_PROP (interval); +} + + +MInterval * +pop_all_properties (MTextPlist *plist, int from, int to) +{ + MInterval *interval; + + /* Be sure to have interval boundary at TO. */ + interval = find_interval (plist, to); + if (interval && interval->start < to) + divide_interval (plist, interval, to); + + /* Be sure to have interval boundary at FROM. */ + interval = find_interval (plist, from); + if (interval->start < from) + { + divide_interval (plist, interval, from); + interval = interval->next; + } + + pop_interval_properties (interval); + while (interval->end < to) + { + MInterval *next = interval->next; + + pop_interval_properties (next); + interval->end = next->end; + interval->next = next->next; + if (interval->next) + interval->next->prev = interval; + if (next == plist->tail) + plist->tail = interval; + if (plist->cache == next) + plist->cache = interval; + free_interval (next); + } + return interval; +} + + +/* Delete volatile text properties between FROM and TO. If DELETING + is nonzero, we are going to delete text, thus both strongly and + weakly volatile properties must be deleted. Otherwise we are going + to modify a text property KEY, thus only strongly volatile + properties whose key is not KEY must be deleted. */ + +static void +prepare_to_modify (MText *mt, int from, int to, MSymbol key, int deleting) +{ + MTextPlist *plist = mt->plist, *prev = NULL; + int mask_bits = MTEXTPROP_VOLATILE_STRONG; + + if (deleting) + mask_bits |= MTEXTPROP_VOLATILE_WEAK; + while (plist) + { + if (plist->key != key + && ! delete_properties (plist, from, to, mask_bits, deleting)) + { + if (prev) + plist = prev->next = free_textplist (plist); + else + plist = mt->plist = free_textplist (plist); + } + else + prev = plist, plist = plist->next; + } +} + +void +extract_text_properties (MText *mt, int from, int to, MSymbol key, + MPlist *plist) +{ + MPlist *top; + MTextPlist *list = get_plist_create (mt, key, 0); + MInterval *interval; + + if (! list) + return; + interval = find_interval (list, from); + if (interval->nprops == 0 + && interval->start <= from && interval->end >= to) + return; + top = plist; + while (interval && interval->start < to) + { + if (interval->nprops == 0) + top = mplist_find_by_key (top, Mnil); + else + { + MPlist *current = top, *place; + int i; + + for (i = 0; i < interval->nprops; i++) + { + MTextProperty *prop = interval->stack[i]; + + place = mplist_find_by_value (current, prop); + if (place) + current = MPLIST_NEXT (place); + else + { + place = mplist_find_by_value (top, prop); + if (place) + { + mplist_pop (place); + if (MPLIST_NEXT (place) == MPLIST_NEXT (current)) + current = place; + } + mplist_push (current, Mt, prop); + current = MPLIST_NEXT (current); + } + } + } + interval = interval->next; + } + return; +} + +#define XML_TEMPLATE "\n\ +\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + ]>\n\ +\n\ +" + + +/* for debugging... */ +#include + +void +dump_interval (MInterval *interval, int indent) +{ + char *prefix = (char *) alloca (indent + 1); + int i; + + memset (prefix, 32, indent); + prefix[indent] = 0; + + fprintf (mdebug__output, "(interval %d-%d (%d)", + interval->start, interval->end, interval->nprops); + for (i = 0; i < interval->nprops; i++) + fprintf (mdebug__output, "\n%s (%d %d/%d %d-%d 0x%x)", + prefix, i, + interval->stack[i]->control.ref_count, + interval->stack[i]->attach_count, + interval->stack[i]->start, interval->stack[i]->end, + (unsigned) interval->stack[i]->val); + fprintf (mdebug__output, ")"); +} + +void +dump_textplist (MTextPlist *plist, int indent) +{ + char *prefix = (char *) alloca (indent + 1); + + memset (prefix, 32, indent); + prefix[indent] = 0; + + fprintf (mdebug__output, "(properties"); + if (! plist) + fprintf (mdebug__output, ")\n"); + else + { + fprintf (mdebug__output, "\n"); + while (plist) + { + MInterval *interval = plist->head; + + fprintf (mdebug__output, "%s (%s", prefix, msymbol_name (plist->key)); + while (interval) + { + fprintf (mdebug__output, " (%d %d", + interval->start, interval->end); + if (interval->nprops > 0) + { + int i; + + for (i = 0; i < interval->nprops; i++) + fprintf (mdebug__output, " 0x%x", + (int) interval->stack[i]->val); + } + fprintf (mdebug__output, ")"); + interval = interval->next; + } + fprintf (mdebug__output, ")\n"); + xassert (check_plist (plist, 0) == 0); + plist = plist->next; + } + } +} + + +/* Internal API */ + +int +mtext__prop_init () +{ + M17N_OBJECT_ADD_ARRAY (text_property_table, "Text property"); + Mtext_prop_serializer = msymbol ("text-prop-serializer"); + Mtext_prop_deserializer = msymbol ("text-prop-deserializer"); + return 0; +} + +void +mtext__prop_fini () +{ + MIntervalPool *pool = interval_pool_root.next; + + while (pool) + { + MIntervalPool *next = pool->next; + free (pool); + pool = next; + } + interval_pool_root.next = NULL; +} + + +/** Free all plists. */ + +void +mtext__free_plist (MText *mt){ + + MTextPlist *plist = mt->plist; + + while (plist) + plist = free_textplist (plist); + mt->plist = NULL; +} + + +/** Extract intervals between FROM and TO of all properties (except + for volatile ones) in PLIST, and make a new plist from them for + M-text MT. */ + +MTextPlist * +mtext__copy_plist (MTextPlist *plist, int from, int to, MText *mt, int pos) +{ + MTextPlist *copy, *this; + + if (from == to) + return NULL; + for (copy = NULL; plist && ! copy; plist = plist->next) + copy = copy_single_property (plist, from, to, mt, pos); + if (! plist) + return copy; + for (; plist; plist = plist->next) + if ((this = copy_single_property (plist, from, to, mt, pos))) + { + this->next = copy; + copy = this; + } + + return copy; +} + +void +mtext__adjust_plist_for_delete (MText *mt, int pos, int len) +{ + MTextPlist *plist; + int to; + + if (len == 0 || pos == mt->nchars) + return; + if (len == mt->nchars) + { + mtext__free_plist (mt); + return; + } + + to = pos + len; + prepare_to_modify (mt, pos, to, Mnil, 1); + for (plist = mt->plist; plist; plist = plist->next) + { + MInterval *interval = pop_all_properties (plist, pos, to); + MInterval *prev = interval->prev, *next = interval->next; + + if (prev) + prev->next = next; + else + plist->head = next; + if (next) + { + adjust_intervals (next, plist->tail, -len); + next->prev = prev; + } + else + plist->tail = prev; + if (prev && next) + next = maybe_merge_interval (plist, prev); + plist->cache = next ? next : prev; + free_interval (interval); + xassert (check_plist (plist, 0) == 0); + } +} + +void +mtext__adjust_plist_for_insert (MText *mt, int pos, int nchars, + MTextPlist *plist) +{ + MTextPlist *pl, *pl_last, *pl2, *p; + int i; + MInterval *interval; + + if (mt->nchars == 0) + { + mtext__free_plist (mt); + mt->plist = plist; + return; + } + if (pos > 0 && pos < mtext_nchars (mt)) + prepare_to_modify (mt, pos, pos, Mnil, 0); + + for (pl_last = NULL, pl = mt->plist; pl; pl_last = pl, pl = pl->next) + { + MInterval *interval, *prev, *next, *head, *tail; + + if (pos == 0) + prev = NULL, next = pl->head; + else if (pos == mtext_nchars (mt)) + prev = pl->tail, next = NULL; + else + { + next = find_interval (pl, pos); + if (next->start < pos) + { + divide_interval (pl, next, pos); + next = next->next; + } + for (i = 0; i < next->nprops; i++) + if (next->stack[i]->start < pos) + split_property (next->stack[i], next); + prev = next->prev; + } + + xassert (check_plist (pl, 0) == 0); + for (p = NULL, pl2 = plist; pl2 && pl->key != pl2->key; + p = pl2, pl2 = p->next); + if (pl2) + { + xassert (check_plist (pl2, pl2->head->start) == 0); + if (p) + p->next = pl2->next; + else + plist = plist->next; + + head = pl2->head; + tail = pl2->tail; + free (pl2); + } + else + { + head = tail = new_interval (pos, pos + nchars); + } + head->prev = prev; + tail->next = next; + if (prev) + prev->next = head; + else + pl->head = head; + if (next) + next->prev = tail; + else + pl->tail = tail; + if (next) + adjust_intervals (next, pl->tail, nchars); + + xassert (check_plist (pl, 0) == 0); + if (prev && prev->nprops > 0) + { + for (interval = prev; + interval->next != next && interval->next->nprops == 0; + interval = interval->next) + for (i = 0; i < interval->nprops; i++) + { + MTextProperty *prop = interval->stack[i]; + + if (prop->control.flag & MTEXTPROP_REAR_STICKY) + PUSH_PROP (interval->next, prop); + } + } + xassert (check_plist (pl, 0) == 0); + if (next && next->nprops > 0) + { + for (interval = next; + interval->prev != prev && interval->prev->nprops == 0; + interval = interval->prev) + for (i = 0; i < interval->nprops; i++) + { + MTextProperty *prop = interval->stack[i]; + + if (prop->control.flag & MTEXTPROP_FRONT_STICKY) + PUSH_PROP (interval->prev, prop); + } + } + + interval = prev ? prev : pl->head; + pl->cache = interval; + while (interval && interval->start <= pos + nchars) + interval = maybe_merge_interval (pl, interval); + xassert (check_plist (pl, 0) == 0); + } + + if (pl_last) + pl_last->next = plist; + else + mt->plist = plist; + + for (; plist; plist = plist->next) + { + plist->cache = plist->head; + if (pos > 0) + { + if (plist->head->nprops) + { + interval = new_interval (0, pos); + interval->next = plist->head; + plist->head->prev = interval; + plist->head = interval; + } + else + plist->head->start = 0; + } + if (pos < mtext_nchars (mt)) + { + if (plist->tail->nprops) + { + interval = new_interval (pos + nchars, + mtext_nchars (mt) + nchars); + interval->prev = plist->tail; + plist->tail->next = interval; + plist->tail = interval; + } + else + plist->tail->end = mtext_nchars (mt) + nchars; + } + xassert (check_plist (plist, 0) == 0); + } +} + +/* len1 > 0 && len2 > 0 */ + +void +mtext__adjust_plist_for_change (MText *mt, int pos, int len1, int len2) +{ + int pos2 = pos + len1; + + prepare_to_modify (mt, pos, pos2, Mnil, 0); + + if (len1 < len2) + { + int diff = len2 - len1; + MTextPlist *plist; + + for (plist = mt->plist; plist; plist = plist->next) + { + MInterval *head = find_interval (plist, pos2); + MInterval *tail = plist->tail; + MTextProperty *prop; + int i; + + if (head) + { + if (head->start == pos2) + head = head->prev; + while (tail != head) + { + for (i = 0; i < tail->nprops; i++) + { + prop = tail->stack[i]; + if (prop->start == tail->start) + prop->start += diff, prop->end += diff; + } + tail->start += diff; + tail->end += diff; + tail = tail->prev; + } + } + for (i = 0; i < tail->nprops; i++) + tail->stack[i]->end += diff; + tail->end += diff; + } + } + else if (len1 > len2) + { + mtext__adjust_plist_for_delete (mt, pos + len2, len1 - len2); + } +} + + +/*** @} */ +#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ + + +/** External API */ + +/*** @addtogroup m17nTextProperty */ +/*** @{ */ + +/*=*/ +/***en + @brief Get the value of the topmost text property. + + The mtext_get_prop () function searches the character at $POS in + M-text $MT for the text property whose key is $KEY. + + @return + If a text property is found, mtext_get_prop () returns the value + of the property. If the property has multiple values, it returns + the topmost one. If no such property is found, it returns @c NULL + without changing the external variable #merror_code. + + If an error is detected, mtext_get_prop () returns @c NULL and + assigns an error code to the external variable #merror_code. + + @note If @c NULL is returned without an error, there are two + possibilities: + + @li the character at $POS does not have a property whose key is $KEY, or + + @li the character does have such a property and its value is @c NULL. + + If you need to distinguish these two cases, use the + mtext_get_prop_values () function instead. */ + +/***ja + @brief �ƥ����ȥץ��ѥƥ��ΰ��־���ͤ�����. + + �ؿ� mtext_get_prop () �ϡ�M-text $MT ��ΰ��� $POS �ˤ���ʸ���Υ� + �����ȥץ��ѥƥ��Τ����������� $KEY �Ǥ����Τ�õ���� + + @return + �ƥ����ȥץ��ѥƥ����ߤĤ���С�mtext_get_prop () �Ϥ��Υץ��ѥƥ� + ���ͤ��֤����ͤ�ʣ��¸�ߤ���Ȥ��ϡ����־���ͤ��֤������Ĥ���ʤ� + ��г����ѿ� #merror_code ���ѹ����뤳�Ȥʤ� @c NULL ���֤��� + + ���顼�����Ф��줿��� mtext_get_prop () �� @c NULL ���֤��������� + �� #merror_code �˥��顼�����ɤ����ꤹ�롣 + + @note ���顼�ʤ��� @c NULL ���֤��줿���ˤ���Ĥβ�ǽ�������롣 + + @li $POS �ΰ��֤�ʸ���� $KEY �򥭡��Ȥ���ץ��ѥƥ�������ʤ��� + + @li ����ʸ���Ϥ��Τ褦�ʥץ��ѥƥ�������������ͤ� @c NULL �Ǥ��롣 + + ������Ĥ���̤���ɬ�פ�������ˤϡ��ؿ� mtext_get_prop_values () + ������˻��Ѥ��뤳�ȡ� + + @latexonly \IPAlabel{mtext_get_prop} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE, @c MERROR_SYMBOL + + @seealso + mtext_get_prop_values (), mtext_put_prop (), mtext_put_prop_values (), + mtext_push_prop (), mtext_pop_prop (), mtext_prop_range () */ + +void * +mtext_get_prop (MText *mt, int pos, MSymbol key) +{ + MTextPlist *plist; + MInterval *interval; + void *val; + + M_CHECK_POS (mt, pos, NULL); + + plist = get_plist_create (mt, key, 0); + if (! plist) + return NULL; + + interval = find_interval (plist, pos); + val = (interval->nprops + ? interval->stack[interval->nprops - 1]->val : NULL); + return val; +} + +/*=*/ + +/***en + @brief Get multiple values of a text property. + + The mtext_get_prop_values () function searches the character at + $POS in M-text $MT for the property whose key is $KEY. If such + a property is found, its values are stored in the memory area + pointed to by $VALUES. $NUM limits the maximum number of stored + values. + + @return + If the operation was successful, mtext_get_prop_values () returns + the number of actually stored values. If the character at $POS + does not have a property whose key is $KEY, the return value is + 0. If an error is detected, mtext_get_prop_values () returns -1 and + assigns an error code to the external variable #merror_code. */ + +/***ja + @brief �ƥ����ȥץ��ѥƥ����ͤ�ʣ��������. + + �ؿ� mtext_get_prop_values () �ϡ�M-text $MT ��� $POS �Ȥ������� + �ˤ���ʸ���Υץ��ѥƥ��Τ����������� $KEY �Ǥ����Τ�õ�����⤷�� + �Τ褦�ʥץ��ѥƥ������Ĥ���С����줬������ (ʣ����) �� $VALUES + �λؤ������ΰ�˳�Ǽ���롣$NUM �ϳ�Ǽ�����ͤο��ξ�¤Ǥ��롣 + + @return + ��������������С�mtext_get_prop_values () �ϼºݤ˥���˳�Ǽ�� + �줿�ͤο����֤���$POS �ΰ��֤�ʸ���� $KEY �򥭡��Ȥ���ץ��ѥƥ� + ������ʤ���� 0 ���֤������顼�����Ф��줿���� -1 ���֤������� + �ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mtext_get_prop_values} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE, @c MERROR_SYMBOL + + @seealso + mtext_get_prop (), mtext_put_prop (), mtext_put_prop_values (), + mtext_push_prop (), mtext_pop_prop (), mtext_prop_range () */ + +int +mtext_get_prop_values (MText *mt, int pos, MSymbol key, + void **values, int num) +{ + MTextPlist *plist; + MInterval *interval; + int nprops; + int i; + int offset; + + M_CHECK_POS (mt, pos, -1); + + plist = get_plist_create (mt, key, 0); + if (! plist) + return 0; + + interval = find_interval (plist, pos); + /* It is assured that INTERVAL is not NULL. */ + nprops = interval->nprops; + if (nprops == 0 || num <= 0) + return 0; + if (nprops == 1 || num == 1) + { + values[0] = interval->stack[nprops - 1]->val; + return 1; + } + + if (nprops <= num) + num = nprops, offset = 0; + else + offset = nprops - num; + for (i = 0; i < num; i++) + values[i] = interval->stack[offset + i]->val; + return num; +} + +/*=*/ + +/***en + @brief Get a list of text property keys at a position of an M-text. + + The mtext_get_prop_keys () function creates an array whose + elements are the keys of text properties found at position $POS in + M-text $MT, and sets *$KEYS to the address of the created array. + The user is responsible to free the memory allocated for + the array. + + @returns + If the operation was successful, mtext_get_prop_keys () returns + the length of the key list. Otherwise it returns -1 and assigns + an error code to the external variable #merror_code. + +*/ + +/***ja + @brief M-text �λ��ꤷ�����֤Υƥ����ȥץ��ѥƥ��Υ����Υꥹ�Ȥ�����. + + �ؿ� mtext_get_prop_keys () �ϡ�M-text $MT ��� $POS �ΰ��֤ˤ��� + ���٤ƤΥƥ����ȥץ��ѥƥ��Υ��������ǤȤ���������ꡢ��������� + ���ɥ쥹�� *$KEYS �����ꤹ�롣��������Τ���˳��ݤ��줿������ + ������Τϥ桼������Ǥ�Ǥ��롣 + + @return + ��������������� mtext_get_prop_keys () ������줿�ꥹ�Ȥ�Ĺ������ + ���������Ǥʤ���� -1 ���֤��������ѿ� #merror_code �˥��顼�����ɤ� + ���ꤹ�롣 +*/ + +/*** + @errors + @c MERROR_RANGE + + @seealso + mtext_get_prop (), mtext_put_prop (), mtext_put_prop_values (), + mtext_get_prop_values (), mtext_push_prop (), mtext_pop_prop () */ + +int +mtext_get_prop_keys (MText *mt, int pos, MSymbol **keys) +{ + MTextPlist *plist; + int i; + + M_CHECK_POS (mt, pos, -1); + for (i = 0, plist = mt->plist; plist; i++, plist = plist->next); + if (i == 0) + { + *keys = NULL; + return 0; + } + MTABLE_MALLOC (*keys, i, MERROR_TEXTPROP); + for (i = 0, plist = mt->plist; plist; plist = plist->next) + { + MInterval *interval = find_interval (plist, pos); + + if (interval->nprops) + (*keys)[i++] = plist->key; + } + return i; +} + +/*=*/ + +/***en + @brief Set a text property. + + The mtext_put_prop () function sets a text property to the + characters between $FROM (inclusive) and $TO (exclusive) in M-text + $MT. $KEY and $VAL specify the key and the value of the text + property. With this function, + +@verbatim + FROM TO +M-text: |<------------|-------- MT ---------|------------>| +PROP : <------------------ OLD_VAL --------------------> +@endverbatim + + becomes + +@verbatim + FROM TO +M-text: |<------------|-------- MT ---------|------------>| +PROP : <-- OLD_VAL-><-------- VAL -------><-- OLD_VAL--> +@endverbatim + + @return + If the operation was successful, mtext_put_prop () returns 0. + Otherwise it returns -1 and assigns an error code to the external + variable #merror_code. */ + +/***ja + @brief �ƥ����ȥץ��ѥƥ������ꤹ��. + + �ؿ� mtext_put_prop () �ϡ�M-text $MT �� $FROM �ʴޤޤ��ˤ��� + $TO �ʴޤޤ�ʤ��ˤ��ϰϤ�ʸ���ˡ������� $KEY ���ͤ� $VAL �Ǥ���� + ���ʥƥ����ȥץ��ѥƥ������ꤹ�롣���δؿ��ˤ�ä� + + +@verbatim + FROM TO +M-text: |<------------|-------- MT ---------|------------>| +PROP: <------------------ OLD_VAL --------------------> +@endverbatim + +�ϼ��Τ褦�ˤʤ롣 + +@verbatim + FROM TO +M-text: |<------------|-------- MT ---------|------------>| +PROP: <-- OLD_VAL-><-------- VAL -------><-- OLD_VAL--> +@endverbatim + + @return + ��������������� mtext_put_prop () �� 0 ���֤��������Ǥʤ���� -1 + ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mtext_put_prop} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE, @c MERROR_SYMBOL + + @seealso + mtext_put_prop_values (), mtext_get_prop (), + mtext_get_prop_values (), mtext_push_prop (), + mtext_pop_prop (), mtext_prop_range () */ + +int +mtext_put_prop (MText *mt, int from, int to, MSymbol key, void *val) +{ + MTextPlist *plist; + MTextProperty *prop; + MInterval *interval; + + M_CHECK_RANGE (mt, from, to, -1, 0); + + prepare_to_modify (mt, from, to, key, 0); + plist = get_plist_create (mt, key, 1); + interval = pop_all_properties (plist, from, to); + prop = new_text_property (mt, from, to, key, val, 0); + PUSH_PROP (interval, prop); + M17N_OBJECT_UNREF (prop); + if (interval->next) + maybe_merge_interval (plist, interval); + if (interval->prev) + maybe_merge_interval (plist, interval->prev); + xassert (check_plist (plist, 0) == 0); + return 0; +} + +/*=*/ + +/***en + @brief Set multiple text properties with the same key. + + The mtext_put_prop_values () function sets a text property to the + characters between $FROM (inclusive) and $TO (exclusive) in M-text + $MT. $KEY and $VALUES specify the key and the values of the text + property. $NUM specifies the number of property values to be set. + + @return + If the operation was successful, mtext_put_prop_values () returns + 0. Otherwise it returns -1 and assigns an error code to the + external variable #merror_code. */ + +/***ja + @brief Ʊ�������Υƥ����ȥץ��ѥƥ���ʣ�����ꤹ��. + + �ؿ� mtext_put_prop_values () �ϡ�M-Text $MT ��$FROM �ʴޤޤ��� + ���� $TO �ʴޤޤ�ʤ��ˤ��ϰϤ�ʸ���ˡ��ƥ����ȥץ��ѥƥ������ꤹ + �롣�ƥ����ȥץ��ѥƥ��Υ����� $KEY �ˤ�äơ���(ʣ����)�� $VALUES + �ˤ�äƻ��ꤵ��롣$NUM �����ꤵ����ͤθĿ��Ǥ��롣 + + @return + ��������������С�mtext_put_prop_values () �� 0 ���֤��������Ǥʤ� + ��� -1 ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mtext_put_prop_values} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE, @c MERROR_SYMBOL + + @seealso + mtext_put_prop (), mtext_get_prop (), mtext_get_prop_values (), + mtext_push_prop (), mtext_pop_prop (), mtext_prop_range () */ + +int +mtext_put_prop_values (MText *mt, int from, int to, + MSymbol key, void **values, int num) +{ + MTextPlist *plist; + MInterval *interval; + int i; + + M_CHECK_RANGE (mt, from, to, -1, 0); + + prepare_to_modify (mt, from, to, key, 0); + plist = get_plist_create (mt, key, 1); + interval = pop_all_properties (plist, from, to); + if (num > 0) + { + PREPARE_INTERVAL_STACK (interval, num); + for (i = 0; i < num; i++) + { + MTextProperty *prop + = new_text_property (mt, from, to, key, values[i], 0); + PUSH_PROP (interval, prop); + M17N_OBJECT_UNREF (prop); + } + } + if (interval->next) + maybe_merge_interval (plist, interval); + if (interval->prev) + maybe_merge_interval (plist, interval->prev); + xassert (check_plist (plist, 0) == 0); + return 0; +} + +/*=*/ + +/***en + @brief Push a text property. + + The mtext_push_prop () function pushes a text property whose key + is $KEY and value is $VAL to the characters between $FROM + (inclusive) and $TO (exclusive) in M-text $MT. With this + function, + +@verbatim + FROM TO +M-text: |<------------|-------- MT ---------|------------>| +PROP : <------------------ OLD_VAL --------------------> +@endverbatim + + becomes + +@verbatim + FROM TO +M-text: |<------------|-------- MT ---------|------------>| +PROP : <------------------- OLD_VAL -------------------> +PROP : <-------- VAL -------> +@endverbatim + + @return + If the operation was successful, mtext_push_prop () returns 0. + Otherwise it returns -1 and assigns an error code to the external + variable #merror_code. */ + +/***ja + @brief �ƥ����ȥץ��ѥƥ���ץå��夹��. + + �ؿ� mtext_push_prop () �ϡ������� $KEY ���ͤ� $VAL �Ǥ���ƥ����� + �ץ��ѥƥ���M-text $MT ��� $FROM �ʴޤޤ��ˤ��� $TO �ʴޤޤ�� + ���ˤ��ϰϤ�ʸ���˥ץå��夹�롣���δؿ��ˤ�ä� + +@verbatim + FROM TO +M-text: |<------------|-------- MT ---------|------------>| +PROP : <------------------ OLD_VAL --------------------> +@endverbatim + �ϼ��Τ褦�ˤʤ롣 +@verbatim + FROM TO +M-text: |<------------|-------- MT ---------|------------>| +PROP : <------------------- OLD_VAL -------------------> +PROP : <-------- VAL -------> +@endverbatim + + @return + ��������������С�mtext_push_prop () �� 0 ���֤��������Ǥʤ���� + -1 ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mtext_push_prop} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE, @c MERROR_SYMBOL + + @seealso + mtext_put_prop (), mtext_put_prop_values (), + mtext_get_prop (), mtext_get_prop_values (), + mtext_pop_prop (), mtext_prop_range () */ + +int +mtext_push_prop (MText *mt, int from, int to, + MSymbol key, void *val) +{ + MTextPlist *plist; + MInterval *head, *tail, *interval; + MTextProperty *prop; + int check_head, check_tail; + + M_CHECK_RANGE (mt, from, to, -1, 0); + + prepare_to_modify (mt, from, to, key, 0); + plist = get_plist_create (mt, key, 1); + + /* Find an interval that covers the position FROM. */ + head = find_interval (plist, from); + + /* If the found interval starts before FROM, divide it at FROM. */ + if (head->start < from) + { + divide_interval (plist, head, from); + head = head->next; + check_head = 0; + } + else + check_head = 1; + + /* Find an interval that ends at TO. If TO is not at the end of an + interval, make one that ends at TO. */ + if (head->end == to) + { + tail = head; + check_tail = 1; + } + else if (head->end > to) + { + divide_interval (plist, head, to); + tail = head; + check_tail = 0; + } + else + { + tail = find_interval (plist, to); + if (! tail) + { + tail = plist->tail; + check_tail = 0; + } + else if (tail->start == to) + { + tail = tail->prev; + check_tail = 1; + } + else + { + divide_interval (plist, tail, to); + check_tail = 0; + } + } + + prop = new_text_property (mt, from, to, key, val, 0); + + /* Push PROP to the current values of intervals between HEAD and TAIL + (both inclusive). */ + for (interval = head; ; interval = interval->next) + { + PUSH_PROP (interval, prop); + if (interval == tail) + break; + } + + M17N_OBJECT_UNREF (prop); + + /* If there is a possibility that TAIL now has the same value as the + next one, check it and concatenate them if necessary. */ + if (tail->next && check_tail) + maybe_merge_interval (plist, tail); + + /* If there is a possibility that HEAD now has the same value as the + previous one, check it and concatenate them if necessary. */ + if (head->prev && check_head) + maybe_merge_interval (plist, head->prev); + + xassert (check_plist (plist, 0) == 0); + return 0; +} + +/*=*/ + +/***en + @brief Pop a text property. + + The mtext_pop_prop () function removes the topmost text property + whose key is $KEY from the characters between $FROM (inclusive) + and and $TO (exclusive) in $MT. + + This function does nothing if characters in the region have no + such text property. With this function, + +@verbatim + FROM TO +M-text: |<------------|-------- MT ---------|------------>| +PROP : <------------------ OLD_VAL --------------------> +@endverbatim + + becomes + +@verbatim + FROM TO +M-text: |<------------|-------- MT ---------|------------>| +PROP : <--OLD_VAL-->| |<--OLD_VAL-->| +@endverbatim + + @return + If the operation was successful, mtext_pop_prop () return 0. + Otherwise it returns -1 and assigns an error code to the external + variable #merror_code. */ + +/***ja + @brief �ƥ����ȥץ��ѥƥ���ݥåפ���. + + �ؿ� mtext_pop_prop () �ϡ������� $KEY �Ǥ���ƥ����ȥץ��ѥƥ��� + �������־�Τ�Τ�M-text $MT �� $FROM �ʴޤޤ��ˤ��� $TO�ʴޤ� + ��ʤ��ˤ��ϰϤ�ʸ������������� + + �����ϰϤ�ʸ�������Τ褦�ʥץ��ѥƥ�������ʤ��ʤ�С����δؿ��ϲ� + �⤷�ʤ������δؿ��ˤ�äơ� + +@verbatim + FROM TO +M-text: |<------------|-------- MT ---------|------------>| +PROP : <------------------ OLD_VAL --------------------> +@endverbatim + �ϰʲ��Τ褦�ˤʤ롣 +@verbatim + FROM TO +M-text: |<------------|-------- MT ---------|------------>| +PROP : <--OLD_VAL-->| |<--OLD_VAL-->| +@endverbatim + + @return + ��������������С�mtext_pop_prop () �� 0 ���֤��������Ǥʤ���� -1 + ���֤��������ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mtext_pop_prop} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE, @c MERROR_SYMBOL + + @seealso + mtext_put_prop (), mtext_put_prop_values (), + mtext_get_prop (), mtext_get_prop_values (), + mtext_push_prop (), mtext_prop_range () */ + +int +mtext_pop_prop (MText *mt, int from, int to, MSymbol key) +{ + MTextPlist *plist; + MInterval *head, *tail; + int check_head = 1; + + if (key == Mnil) + MERROR (MERROR_TEXTPROP, -1); + M_CHECK_RANGE (mt, from, to, -1, 0); + plist = get_plist_create (mt, key, 0); + if (! plist) + return 0; + + /* Find an interval that covers the position FROM. */ + head = find_interval (plist, from); + if (head->end >= to + && head->nprops == 0) + /* No property to pop. */ + return 0; + + prepare_to_modify (mt, from, to, key, 0); + + /* If the found interval starts before FROM and has value(s), divide + it at FROM. */ + if (head->start < from) + { + if (head->nprops > 0) + { + divide_interval (plist, head, from); + check_head = 0; + } + else + from = head->end; + head = head->next; + } + + /* Pop the topmost text property from each interval following HEAD. + Stop at an interval that ends after TO. */ + for (tail = head; tail && tail->end <= to; tail = tail->next) + if (tail->nprops > 0) + POP_PROP (tail); + + if (tail) + { + if (tail->start < to) + { + if (tail->nprops > 0) + { + divide_interval (plist, tail, to); + POP_PROP (tail); + } + to = tail->start; + } + else + to = tail->end; + } + else + to = plist->tail->start; + + /* If there is a possibility that HEAD now has the same text + properties as the previous one, check it and concatenate them if + necessary. */ + if (head->prev && check_head) + head = head->prev; + while (head && head->end <= to) + head = maybe_merge_interval (plist, head); + + xassert (check_plist (plist, 0) == 0); + return 0; +} + +/*=*/ + +/***en + @brief Find the range where the value of a text property is the same. + + The mtext_prop_range () function investigates the extent where all + characters have the same value for a text property. It first + finds the value of the property specified by $KEY of the character + at $POS in M-text $MT. Then it checks if adjacent characters have + the same value for the property $KEY. The beginning and the end + of the found range are stored to the variable pointed to by $FROM + and $TO. The character position stored in $FROM is inclusive but + that in $TO is exclusive; this fashion is compatible with the + range specification in the mtext_put_prop () function, etc. + + If $DEEPER is not 0, not only the topmost but also all the stacked + properties whose key is $KEY are compared. + + If $FROM is @c NULL, the beginning of range is not searched for. If + $TO is @c NULL, the end of range is not searched for. + + @return + + If the operation was successful, mtext_prop_range () returns the + number of values the property $KEY has at pos. Otherwise it + returns -1 and assigns an error code to the external variable @c + merror_code. */ + +/***ja + @brief �ƥ����ȥץ��ѥƥ���Ʊ���ͤ�Ȥ��ϰϤ�Ĵ�٤�. + + �ؿ� mtext_prop_range () �ϡ����ꤷ���ƥ����ȥץ��ѥƥ����ͤ�Ʊ�� + �Ǥ���Ϣ³����ʸ�����ϰϤ�Ĵ�٤롣�ޤ� M-text $MT �� $POS �ΰ��֤� + ����ʸ���Υץ��ѥƥ��Τ��������� $KEY �ǻ��ꤵ�줿����ͤ򸫤Ĥ� + �롣�����������ʸ���� $KEY �Υץ��ѥƥ����ͤ�Ʊ���Ǥ��뤫�ɤ����� + Ĵ�٤롣���Ĥ����ϰϤκǽ�ȺǸ�򡢤��줾�� $FROM �� $TO �˥ݥ��� + �Ȥ�����ѿ�����¸���롣$FROM ����¸�����ʸ���ΰ��֤ϸ��Ĥ����ϰ� + �˴ޤޤ�뤬��$TO �ϴޤޤ�ʤ�����$TO ������Ʊ���ͤ�Ȥ��ϰϤϽ��� + �롣�ˤ����ϰϻ���ˡ�ϡ��ؿ� mtext_put_prop () �ʤɤȶ��̤Ǥ��롣 + + $DEEPER �� 0 �Ǥʤ���С�$KEY �Ȥ�����������ĥץ��ѥƥ��Τ������� + ��Τ�Τ����Ǥʤ��������å���Τ��٤ƤΤ�Τ���Ӥ���롣 + + $FROM �� @c NULL �ʤ�С��ϰϤλϤޤ��õ�����ʤ���$TO �� @c NULL + �ʤ�С��ϰϤν����õ�����ʤ��� + + @return + ��������������С�mtext_prop_range () �� $KEY �ץ��ѥƥ����ͤο��� + �֤��������Ǥʤ����-1 ���֤��� �����ѿ� #merror_code �˥��顼���� + �ɤ����ꤹ�롣 + + @latexonly \IPAlabel{mtext_prop_range} @endlatexonly */ + +/*** + @errors + @c MERROR_RANGE, @c MERROR_SYMBOL + + @seealso + mtext_put_prop (), mtext_put_prop_values (), + mtext_get_prop (), mtext_get_prop_values (), + mtext_pop_prop (), mtext_push_prop () */ + +int +mtext_prop_range (MText *mt, MSymbol key, int pos, + int *from, int *to, int deeper) +{ + MTextPlist *plist; + MInterval *interval, *temp; + void *val; + int nprops; + + M_CHECK_POS (mt, pos, -1); + + plist = get_plist_create (mt, key, 0); + if (! plist) + { + if (from) *from = 0; + if (to) *to = mtext_nchars (mt); + return 0; + } + + interval = find_interval (plist, pos); + nprops = interval->nprops; + if (deeper || ! nprops) + { + if (from) *from = interval->start; + if (to) *to = interval->end; + return interval->nprops; + } + + val = nprops ? interval->stack[nprops - 1] : NULL; + + if (from) + { + for (temp = interval; + temp->prev + && (temp->prev->nprops + ? (nprops + && (val == temp->prev->stack[temp->prev->nprops - 1])) + : ! nprops); + temp = temp->prev); + *from = temp->start; + } + + if (to) + { + for (temp = interval; + temp->next + && (temp->next->nprops + ? (nprops + && val == temp->next->stack[temp->next->nprops - 1]) + : ! nprops); + temp = temp->next); + *to = temp->end; + } + + return nprops; +} + +/***en + @brief Create a text property. + + The mtext_property () function returns a newly allocated text + property whose key is $KEY and value is $VAL. The created text + property is not attached to any M-text, i.e. it is detached. + + $CONTROL_BITS must be 0 or logical OR of @c enum @c + MTextPropertyControl. */ + +/***ja + @brief �ƥ����ȥץ��ѥƥ�����������. + + �ؿ� mtext_property () �� $KEY �򥭡���$VAL ���ͤȤ��뿷��������� + �Ƥ�줿�ƥ����ȥץ��ѥƥ����֤������������ƥ����ȥץ��ѥƥ��Ϥ��� + �ʤ� M-text �ˤ��ղä���Ƥ��ʤ������ʤ��ʬΥ���� (detached) ���롣 + + $CONTROL_BITS �� 0 �Ǥ��뤫 @c enum @c MTextPropertyControl ������ + OR �Ǥʤ��ƤϤʤ�ʤ��� */ + +MTextProperty * +mtext_property (MSymbol key, void *val, int control_bits) +{ + return new_text_property (NULL, 0, 0, key, val, control_bits); +} + +/***en + @brief Return the M-text of a text property. + + The mtext_property_mtext () function returns the M-text to which + text property $PROP is attached. If $PROP is currently detached, + NULL is returned. */ + +/***ja + @brief ����ƥ����ȥץ��ѥƥ������ M-text ���֤�. + + �ؿ� mtext_property_mtext () �ϡ��ƥ����ȥץ��ѥƥ�$PROP ���ղä� + ��Ƥ��� M-text ���֤������λ����� $PROP ��ʬΥ���Ƥ���� NULL �� + �֤��� */ + +MText * +mtext_property_mtext (MTextProperty *prop) +{ + return prop->mt; +} + +/***en + @brief Return the key of a text property. + + The mtext_property_key () function returns the key (symbol) of + text property $PROP. */ + +/***ja + @brief �ƥ����ȥץ��ѥƥ��Υ������֤�. + + �ؿ� mtext_property_key () �ϡ��ƥ����ȥץ��ѥƥ� $PROP �Υ����ʥ� + ��ܥ�ˤ��֤��� */ + +MSymbol +mtext_property_key (MTextProperty *prop) +{ + return prop->key; +} + +/***en + @brief Return the value of a text property. + + The mtext_property_value () function returns the value of text + property $PROP. */ + +/***ja + @brief �ƥ����ȥץ��ѥƥ����ͤ��֤�. + + �ؿ� mtext_property_value () �ϡ��ƥ����ȥץ��ѥƥ� $PROP ���ͤ��� + ���� */ + +void * +mtext_property_value (MTextProperty *prop) +{ + return prop->val; +} + +/***en + @brief Return the start position of a text property. + + The mtext_property_start () function returns the start position of + text property $PROP. The start position is a character position + of an M-text where $PROP begins. If $PROP is detached, it returns + -1. */ + +/***ja + @brief �ƥ����ȥץ��ѥƥ��γ��ϰ��֤��֤�. + + �ؿ� mtext_property_start () �ϡ��ƥ����ȥץ��ѥƥ� $PROP �γ��ϰ� + �֤��֤������ϰ��֤Ȥ� M-text ��� $PROP ���Ϥޤ�ʸ�����֤Ǥ��롣 + $PROP ��ʬΥ����Ƥ���С�-1 ���֤��� */ + +int +mtext_property_start (MTextProperty *prop) +{ + return (prop->mt ? prop->start : -1); +} + +/***en + @brief Return the end position of a text property. + + The mtext_property_end () function returns the end position of + text property $PROP. The end position is a character position of + an M-text where $PROP ends. If $PROP is detached, it returns + -1. */ + +/***ja + @brief �ƥ����ȥץ��ѥƥ��ν�λ���֤��֤�. + + �ؿ� mtext_property_end () �ϡ��ƥ����ȥץ��ѥƥ� $PROP �ν�λ���� + ���֤�����λ���֤Ȥ� M-text ��� $PROP ������ʸ�����֤Ǥ��롣$PROP + ��ʬΥ����Ƥ���С�-1 ���֤��� */ + +int +mtext_property_end (MTextProperty *prop) +{ + return (prop->mt ? prop->end : -1); +} + +/***en + @brief Get the topmost text property. + + The mtext_get_property () function searches the character at + position $POS in M-text $MT for a text property whose key is $KEY. + + @return + If a text property is found, mtext_get_property () returns it. If + there are multiple text properties, it returns the topmost one. + If no such property is found, it returns @c NULL without changing + the external variable #merror_code. + + If an error is detected, mtext_get_property () returns @c NULL and + assigns an error code to the external variable #merror_code. */ + +/***ja + @brief ���־�Υƥ����ȥץ��ѥƥ�������. + + �ؿ� mtext_get_property () �� M-text $MT �ΰ��� $POS ��ʸ�������� + �� $KEY �Ǥ���ƥ����ȥץ��ѥƥ�����Ĥ��ɤ�����Ĵ�٤롣 + + @return + �ƥ����ȥץ��ѥƥ������Ĥ���С�mtext_get_property () �Ϥ�����֤��� + ʣ��������ˤϡ����־�Τ�Τ��֤������Ĥ���ʤ���С������ѿ� + #merror_code ���Ѥ��뤳�Ȥʤ� @c NULL ���֤��� + + ���顼�����Ф��줿��� mtext_get_property () �� @c NULL ���֤����� + ���ѿ� #merror_code �˥��顼�����ɤ����ꤹ�롣 */ + +MTextProperty * +mtext_get_property (MText *mt, int pos, MSymbol key) +{ + MTextPlist *plist; + MInterval *interval; + + M_CHECK_POS (mt, pos, NULL); + + plist = get_plist_create (mt, key, 0); + if (! plist) + return NULL; + + interval = find_interval (plist, pos); + if (! interval->nprops) + return NULL; + return interval->stack[interval->nprops - 1]; +} + +/***en + @brief Get multiple text properties. + + The mtext_get_properties () function searches the character at + $POS in M-text $MT for properties whose key is $KEY. If such + properties are found, they are stored in the memory area pointed + to by $PROPS. $NUM limits the maximum number of stored + properties. + + @return + If the operation was successful, mtext_get_properties () returns + the number of actually stored properties. If the character at + $POS does not have a property whose key is $KEY, the return value + is 0. If an error is detected, mtext_get_properties () returns -1 + and assigns an error code to the external variable #merror_code. */ + +/***ja + @brief ʣ���Υƥ����ȥץ��ѥƥ�������. + + �ؿ� mtext_get_properties () �� M-text $MT �ΰ��� $POS ��ʸ�������� + �� $KEY �Ǥ���ƥ����ȥץ��ѥƥ�����Ĥ��ɤ�����Ĵ�٤롣���Τ褦�� + �ץ��ѥƥ����ߤĤ���С�$PROPS ���ؤ������ΰ����¸���롣$NUM �� + ��¸�����ץ��ѥƥ��ο��ξ�¤Ǥ��롣 + + @return + ��������������С�mtext_get_properties () �ϼºݤ���¸�����ץ��ѥƥ� + �ο����֤���$POS �ΰ��֤�ʸ���������� $KEY �Ǥ���ץ��ѥƥ������ + �ʤ���С�0 ���֤롣���顼�����Ф��줿���ˤϡ� + mtext_get_properties () �� -1 ���֤��������ѿ� #merror_code �˥��顼 + �����ɤ����ꤹ�롣 */ + +int +mtext_get_properties (MText *mt, int pos, MSymbol key, + MTextProperty **props, int num) +{ + MTextPlist *plist; + MInterval *interval; + int nprops; + int i; + int offset; + + M_CHECK_POS (mt, pos, -1); + + plist = get_plist_create (mt, key, 0); + if (! plist) + return 0; + + interval = find_interval (plist, pos); + /* It is assured that INTERVAL is not NULL. */ + nprops = interval->nprops; + if (nprops == 0 || num <= 0) + return 0; + if (nprops == 1 || num == 1) + { + props[0] = interval->stack[nprops - 1]; + return 1; + } + + if (nprops <= num) + num = nprops, offset = 0; + else + offset = nprops - num; + for (i = 0; i < num; i++) + props[i] = interval->stack[offset + i]; + return num; +} + +/***en + @brief Attach a text property to an M-text. + + The mtext_attach_property () function attaches text property $PROP + to the range between $FROM and $TO in M-text $MT. If $PROP is + already attached to an M-text, it is detached before attached to + $MT. + + @return + If the operation was successful, mtext_attach_property () returns + 0. Otherwise it returns -1 and assigns an error code to the + external variable #merror_code. */ + +/***ja + @brief M-text�˥ƥ����ȥץ��ѥƥ����ղä���. + + �ؿ� mtext_attach_property () �ϡ�M-text $MT �� $FROM ���� $TO �� + �Ǥ��ΰ�˥ƥ����ȥץ��ѥƥ� $PROP ���ղä��롣�⤷ $PROP ������ + M-text ���ղä���Ƥ���С�$MT ���ղä�������ʬΥ����롣 + + @return + ��������������С�mtext_attach_property () �� 0 ���֤��������Ǥʤ� + ��� -1 ���֤��Ƴ����ѿ�#merror_code �˥��顼�����ɤ����ꤹ�롣 */ + + +int +mtext_attach_property (MText *mt, int from, int to, MTextProperty *prop) +{ + MTextPlist *plist; + MInterval *interval; + + M_CHECK_RANGE (mt, from, to, -1, 0); + + M17N_OBJECT_REF (prop); + if (prop->mt) + mtext_detach_property (prop); + prepare_to_modify (mt, from, to, prop->key, 0); + plist = get_plist_create (mt, prop->key, 1); + xassert (check_plist (plist, 0) == 0); + interval = pop_all_properties (plist, from, to); + xassert (check_plist (plist, 0) == 0); + prop->mt = mt; + prop->start = from; + prop->end = to; + PUSH_PROP (interval, prop); + M17N_OBJECT_UNREF (prop); + xassert (check_plist (plist, 0) == 0); + if (interval->next) + maybe_merge_interval (plist, interval); + if (interval->prev) + maybe_merge_interval (plist, interval->prev); + xassert (check_plist (plist, 0) == 0); + return 0; +} + +/***en + @brief Detach a text property from an M-text. + + The mtext_detach_property () function makes text property $PROP + detached. + + @return + This function always returns 0. */ + +/***ja + @brief M-text ����ƥ����ȥץ��ѥƥ���ʬΥ����. + + �ؿ� mtext_detach_property () �ϥƥ����ȥץ��ѥƥ� $PROP ��ʬΥ���롣 + + @return + ���δؿ��Ͼ�� 0 ���֤��� */ + +int +mtext_detach_property (MTextProperty *prop) +{ + MTextPlist *plist; + int start = prop->start, end = prop->end; + + if (! prop->mt) + return 0; + prepare_to_modify (prop->mt, start, end, prop->key, 0); + plist = get_plist_create (prop->mt, prop->key, 0); + xassert (plist); + detach_property (plist, prop, NULL); + return 0; +} + +/***en + @brief Push a text property onto an M-text. + + The mtext_push_property () function pushes text property $PROP to + the characters between $FROM (inclusive) and $TO (exclusive) in + M-text $MT. + + @return + If the operation was successful, mtext_push_property () returns + 0. Otherwise it returns -1 and assigns an error code to the + external variable #merror_code. */ + +/***ja + @brief M-text �˥ƥ����ȥץ��ѥƥ���ץå��夹��. + + �ؿ� mtext_push_property () �ϡ��ƥ����ȥץ��ѥƥ� $PROP �� + M-text $MT ��� $FROM �ʴޤޤ��ˤ��� $TO �ʴޤޤ�ʤ��ˤ��ϰϤ� + ʸ���˥ץå��夹�롣 + + @return + ��������������С�mtext_push_property () �� 0 ���֤��������Ǥʤ� + ��� -1 ���֤��Ƴ����ѿ�#merror_code �˥��顼�����ɤ����ꤹ�롣 */ + + +int +mtext_push_property (MText *mt, int from, int to, MTextProperty *prop) +{ + MTextPlist *plist; + MInterval *head, *tail, *interval; + int check_head, check_tail; + + M_CHECK_RANGE (mt, from, to, -1, 0); + + M17N_OBJECT_REF (prop); + if (prop->mt) + mtext_detach_property (prop); + prepare_to_modify (mt, from, to, prop->key, 0); + plist = get_plist_create (mt, prop->key, 1); + prop->mt = mt; + prop->start = from; + prop->end = to; + + /* Find an interval that covers the position FROM. */ + head = find_interval (plist, from); + + /* If the found interval starts before FROM, divide it at FROM. */ + if (head->start < from) + { + divide_interval (plist, head, from); + head = head->next; + check_head = 0; + } + else + check_head = 1; + + /* Find an interval that ends at TO. If TO is not at the end of an + interval, make one that ends at TO. */ + if (head->end == to) + { + tail = head; + check_tail = 1; + } + else if (head->end > to) + { + divide_interval (plist, head, to); + tail = head; + check_tail = 0; + } + else + { + tail = find_interval (plist, to); + if (! tail) + { + tail = plist->tail; + check_tail = 0; + } + else if (tail->start == to) + { + tail = tail->prev; + check_tail = 1; + } + else + { + divide_interval (plist, tail, to); + check_tail = 0; + } + } + + /* Push PROP to the current values of intervals between HEAD and TAIL + (both inclusive). */ + for (interval = head; ; interval = interval->next) + { + PUSH_PROP (interval, prop); + if (interval == tail) + break; + } + + /* If there is a possibility that TAIL now has the same value as the + next one, check it and concatenate them if necessary. */ + if (tail->next && check_tail) + maybe_merge_interval (plist, tail); + + /* If there is a possibility that HEAD now has the same value as the + previous one, check it and concatenate them if necessary. */ + if (head->prev && check_head) + maybe_merge_interval (plist, head->prev); + + M17N_OBJECT_UNREF (prop); + xassert (check_plist (plist, 0) == 0); + return 0; +} + +/***en + @brief Symbol for specifying serializer functions. + + To serialize a text property, the user must supply a serializer + function for that text property. This is done by giving a symbol + property whose key is #Mtext_prop_serializer and value is a + pointer to an appropriate serializer function. + + @seealso + mtext_serialize (), #MTextPropSerializeFunc + */ + +/***ja + @brief ���ꥢ�饤���ؿ�����ꤹ�륷��ܥ�. + + �ƥ����ȥץ��ѥƥ��򥷥ꥢ�饤�����뤿��ˤϡ����Υƥ����ȥץ��� + �ƥ��ѤΥ��ꥢ�饤���ؿ���Ϳ���ʤ��ƤϤʤ�ʤ�������Ū�ˤϡ� + #Mtext_prop_serializer �򥭡��Ȥ���Ŭ�ڤʥ��ꥢ�饤���ؿ��ؤΥݥ� + �󥿤��ͤȤ��륷��ܥ�ץ��ѥƥ�����ꤹ�롣 + + @seealso + mtext_serialize (), #MTextPropSerializeFunc + */ +MSymbol Mtext_prop_serializer; + +/***en + @brief Symbol for specifying deserializer functions. + + To deserialize a text property, the user must supply a deserializer + function for that text property. This is done by giving a symbol + property whose key is #Mtext_prop_deserializer and value is a + pointer to an appropriate deserializer function. + + @seealso + mtext_deserialize (), #MTextPropSerializeFunc + */ + +/***ja + @brief �ǥ��ꥢ�饤���ؿ�����ꤹ�륷��ܥ�. + + �ƥ����ȥץ��ѥƥ���ǥ��ꥢ�饤�����뤿��ˤϡ����Υƥ����ȥץ� + �ѥƥ��ѤΥǥ��ꥢ�饤���ؿ���Ϳ���ʤ��ƤϤʤ�ʤ�������Ū�ˤϡ� + #Mtext_prop_deserializer �򥭡��Ȥ���Ŭ�ڤʥǥ��ꥢ�饤���ؿ��ؤ� + �ݥ��󥿤��ͤȤ��륷��ܥ�ץ��ѥƥ�����ꤹ�롣 + + @seealso + mtext_deserialize (), #MTextPropSerializeFunc + */ +MSymbol Mtext_prop_deserializer; + +/***en + @brief Serialize text properties in an M-text. + + The mtext_serialize () function serializes the text between $FROM + and $TO in M-text $MT. The serialized result is an M-text in a + form of XML. $PROPERTY_LIST limits the text properties to be + serialized. Only those text properties whose key + + @li appears as the value of an element in $PROPERTY_LIST, and + @li has the symbol property #Mtext_prop_serializer + + are serialized as a "property" element in the resulting XML + representation. + + The DTD of the generated XML is as follows: + +@verbatim + + + + + + + + + ]> +@endverbatim + + This function depends on the libxml2 library. If the m17n library + is configured without libxml2, this function always fails. + + @return + If the operation was successful, mtext_serialize () returns an + M-text in the form of XML. Otherwise it returns @c NULL and assigns an + error code to the external variable #merror_code. + + @seealso + mtext_deserialize (), #Mtext_prop_serializer */ + +/***ja + @brief M-text ��Υƥ����ȥץ��ѥƥ��򥷥ꥢ�饤������. + + �ؿ� mtext_serialize () �� M-text $MT �� $FROM ���� $TO �ޤǤΥƥ� + ���Ȥ򥷥ꥢ�饤�����롣���ꥢ�饤��������̤� XML ������ M-text �� + ���롣 $PROPERTY_LIST �ϥ��ꥢ�饤�������ƥ����ȥץ��ѥƥ������ + ���롣�оݤȤʤ�ƥ����ȥץ��ѥƥ��ϡ����Υ����� + + @li $PROPERTY_LIST �����Ǥ��ͤȤ��Ƹ���졢���� + @li ����ܥ�ץ��ѥƥ� #Mtext_prop_serializer ����� + + ��ΤΤߤǤ��롣���ξ����������ƥ����ȥץ��ѥƥ��ϡ���������� + XML ɽ����� "property" ���Ǥ˥��ꥢ�饤������롣 + + ��������� XML �� DTD �ϰʲ����̤�: + +@verbatim + + + + + + + + + ]> +@endverbatim + + ���δؿ��� libxml2 �饤�֥��˰�¸���롣m17n �饤�֥�꤬libxml2 + ̵�������ꤵ��Ƥ����硢���δؿ��Ͼ�˼��Ԥ��롣 + + @return + ��������������С�mtext_serialize () �� XML ������ M-text ���֤��� + �����Ǥʤ���� @c NULL ���֤��Ƴ����ѿ�#merror_code �˥��顼������ + �����ꤹ�롣 + + @seealso + mtext_deserialize (), #Mtext_prop_serializer */ + +MText * +mtext_serialize (MText *mt, int from, int to, MPlist *property_list) +{ +#ifdef HAVE_XML2 + MPlist *plist, *pl; + MTextPropSerializeFunc func; + MText *work; + xmlDocPtr doc; + xmlNodePtr node; + unsigned char *ptr; + int n; + + M_CHECK_RANGE (mt, from, to, NULL, NULL); + if (mt->format != MTEXT_FORMAT_US_ASCII + && mt->format != MTEXT_FORMAT_UTF_8) + mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8); + if (MTEXT_DATA (mt)[mtext_nbytes (mt)] != 0) + MTEXT_DATA (mt)[mtext_nbytes (mt)] = 0; + doc = xmlParseMemory (XML_TEMPLATE, strlen (XML_TEMPLATE) + 1); + node = xmlDocGetRootElement (doc); + + plist = mplist (); + MPLIST_DO (pl, property_list) + { + MSymbol key = MPLIST_VAL (pl); + + func = ((MTextPropSerializeFunc) + msymbol_get_func (key, Mtext_prop_serializer)); + if (func) + extract_text_properties (mt, from, to, key, plist); + } + + work = mtext (); + MPLIST_DO (pl, plist) + { + MTextProperty *prop = MPLIST_VAL (pl); + char buf[256]; + MPlist *serialized_plist; + xmlNodePtr child; + + func = ((MTextPropSerializeFunc) + msymbol_get_func (prop->key, Mtext_prop_serializer)); + serialized_plist = (func) (prop->val); + if (! serialized_plist) + continue; + mtext_reset (work); + mplist__serialize (work, serialized_plist, 0); + child = xmlNewChild (node, NULL, (xmlChar *) "property", NULL); + xmlSetProp (child, (xmlChar *) "key", + (xmlChar *) MSYMBOL_NAME (prop->key)); + xmlSetProp (child, (xmlChar *) "value", (xmlChar *) MTEXT_DATA (work)); + sprintf (buf, "%d", prop->start - from); + xmlSetProp (child, (xmlChar *) "from", (xmlChar *) buf); + sprintf (buf, "%d", prop->end - from); + xmlSetProp (child, (xmlChar *) "to", (xmlChar *) buf); + sprintf (buf, "%d", prop->control.flag); + xmlSetProp (child, (xmlChar *) "control", (xmlChar *) buf); + xmlAddChild (node, xmlNewText ((xmlChar *) "\n")); + + M17N_OBJECT_UNREF (serialized_plist); + } + M17N_OBJECT_UNREF (plist); + + if (from > 0 || to < mtext_nchars (mt)) + mtext_copy (work, 0, mt, from, to); + else + { + M17N_OBJECT_UNREF (work); + work = mt; + } + for (from = 0, to = mtext_nchars (mt); from <= to; from++) + { + ptr = MTEXT_DATA (mt) + POS_CHAR_TO_BYTE (mt, from); + xmlNewTextChild (node, NULL, (xmlChar *) "body", (xmlChar *) ptr); + from = mtext_character (mt, from, to, 0); + if (from < 0) + from = to; + } + + xmlDocDumpMemoryEnc (doc, (xmlChar **) &ptr, &n, "UTF-8"); + if (work == mt) + work = mtext (); + mtext__cat_data (work, ptr, n, MTEXT_FORMAT_UTF_8); + return work; +#else /* not HAVE_XML2 */ + MERROR (MERROR_TEXTPROP, NULL); +#endif /* not HAVE_XML2 */ +} + +/***en + @brief Deserialize text properties in an M-text. + + The mtext_deserialize () function deserializes M-text $MT. $MT + must be an XML having the following DTD. + +@verbatim + + + + + + + + + ]> +@endverbatim + + This function depends on the libxml2 library. If the m17n library + is configured without libxml2, this function always fail. + + @return + If the operation was successful, mtext_deserialize () returns the + resulting M-text. Otherwise it returns @c NULL and assigns an error + code to the external variable #merror_code. + + @seealso + mtext_serialize (), #Mtext_prop_deserializer */ + +/***ja + @brief M-text ��Υƥ����ȥץ��ѥƥ���ǥ��ꥢ�饤������. + + �ؿ� mtext_deserialize () �� M-text $MT ��ǥ��ꥢ�饤�����롣$MT + �ϼ��� DTD ����� XML �Ǥʤ��ƤϤʤ�ʤ��� + +@verbatim + + + + + + + + + ]> +@endverbatim + + ���δؿ��� libxml2 �饤�֥��˰�¸���롣m17n �饤�֥�꤬libxml2 + ̵�������ꤵ��Ƥ����硢���δؿ��Ͼ�˼��Ԥ��롣 + + @return + ��������������С�mtext_serialize () ������줿 M-text �� + �֤��������Ǥʤ���� @c NULL ���֤��Ƴ����ѿ� #merror_code �˥��顼 + �����ɤ����ꤹ�롣 + + @seealso + mtext_serialize (), #Mtext_prop_deserializer */ + +MText * +mtext_deserialize (MText *mt) +{ +#ifdef HAVE_XML2 + xmlDocPtr doc; + xmlNodePtr node; + xmlXPathContextPtr context; + xmlXPathObjectPtr result; + xmlChar *body_str, *key_str, *val_str, *from_str, *to_str, *ctl_str; + int i; + + if (mt->format > MTEXT_FORMAT_UTF_8) + MERROR (MERROR_TEXTPROP, NULL); + doc = xmlParseMemory ((char *) MTEXT_DATA (mt), mtext_nbytes (mt)); + if (! doc) + MERROR (MERROR_TEXTPROP, NULL); + node = xmlDocGetRootElement (doc); + if (! node) + { + xmlFreeDoc (doc); + MERROR (MERROR_TEXTPROP, NULL); + } + if (xmlStrcmp (node->name, (xmlChar *) "mtext")) + { + xmlFreeDoc (doc); + MERROR (MERROR_TEXTPROP, NULL); + } + + context = xmlXPathNewContext (doc); + result = xmlXPathEvalExpression ((xmlChar *) "//body", context); + if (xmlXPathNodeSetIsEmpty (result->nodesetval)) + { + xmlFreeDoc (doc); + MERROR (MERROR_TEXTPROP, NULL); + } + for (i = 0, mt = mtext (); i < result->nodesetval->nodeNr; i++) + { + if (i > 0) + mtext_cat_char (mt, 0); + node = (xmlNodePtr) result->nodesetval->nodeTab[i]; + body_str = xmlNodeListGetString (doc, node->xmlChildrenNode, 1); + if (body_str) + { + mtext__cat_data (mt, body_str, strlen ((char *) body_str), + MTEXT_FORMAT_UTF_8); + xmlFree (body_str); + } + } + + result = xmlXPathEvalExpression ((xmlChar *) "//property", context); + if (! xmlXPathNodeSetIsEmpty (result->nodesetval)) + for (i = 0; i < result->nodesetval->nodeNr; i++) + { + MSymbol key; + MTextPropDeserializeFunc func; + MTextProperty *prop; + MPlist *plist; + int from, to, control; + void *val; + + key_str = xmlGetProp (result->nodesetval->nodeTab[i], + (xmlChar *) "key"); + val_str = xmlGetProp (result->nodesetval->nodeTab[i], + (xmlChar *) "value"); + from_str = xmlGetProp (result->nodesetval->nodeTab[i], + (xmlChar *) "from"); + to_str = xmlGetProp (result->nodesetval->nodeTab[i], + (xmlChar *) "to"); + ctl_str = xmlGetProp (result->nodesetval->nodeTab[i], + (xmlChar *) "control"); + + key = msymbol ((char *) key_str); + func = ((MTextPropDeserializeFunc) + msymbol_get_func (key, Mtext_prop_deserializer)); + if (! func) + continue; + plist = mplist__from_string (val_str, strlen ((char *) val_str)); + if (! plist) + continue; + if (sscanf ((char *) from_str, "%d", &from) != 1 + || from < 0 || from >= mtext_nchars (mt)) + continue; + if (sscanf ((char *) to_str, "%d", &to) != 1 + || to <= from || to > mtext_nchars (mt)) + continue; + if (sscanf ((char *) ctl_str, "%d", &control) != 1 + || control < 0 || control > MTEXTPROP_CONTROL_MAX) + continue; + val = (func) (plist); + M17N_OBJECT_UNREF (plist); + prop = mtext_property (key, val, control); + if (key->managing_key) + M17N_OBJECT_UNREF (val); + mtext_push_property (mt, from, to, prop); + M17N_OBJECT_UNREF (prop); + + xmlFree (key_str); + xmlFree (val_str); + xmlFree (from_str); + xmlFree (to_str); + xmlFree (ctl_str); + } + xmlXPathFreeContext (context); + xmlFreeDoc (doc); + return mt; +#else /* not HAVE_XML2 */ + MERROR (MERROR_TEXTPROP, NULL); +#endif /* not HAVE_XML2 */ +} + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ diff --git a/src/textprop.h b/src/textprop.h new file mode 100644 index 0000000..0caab8b --- /dev/null +++ b/src/textprop.h @@ -0,0 +1,74 @@ +/* textproc.h -- header file for the text property module. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO112 + + This file is part of the m17n library. + + The m17n 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 m17n 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 m17n library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA. */ + +#ifndef _M17N_TEXTPROP_H_ +#define _M17N_TEXTPROP_H_ + +/** MTextProperty is the structure for a text property object. While + attached, it is stored in the stacks of intervals covering the + range from MTextProperty->start to MTextProperty->end. */ + +struct MTextProperty +{ + /** Common header for a managed object. */ + M17NObject control; + + /** Number of intervals the property is attached. When it becomes + zero, the property is detached. */ + unsigned attach_count; + + /** M-text to which the property is attaced. The value NULL means + that the property is detached. */ + MText *mt; + + /** Region of if the property is attached to it. */ + int start, end; + + /** Key of the property. */ + MSymbol key; + + /** Value of the property. */ + void *val; +}; + +#define MTEXTPROP_START(prop) (prop)->start +#define MTEXTPROP_END(prop) (prop)->end +#define MTEXTPROP_KEY(prop) (prop)->key +#define MTEXTPROP_VAL(prop) (prop)->val + +extern struct MTextPlist *mtext__copy_plist (struct MTextPlist *, + int from, int to, + MText *mt, int pos); + +extern void mtext__free_plist (MText *mt); + +extern void mtext__adjust_plist_for_delete (MText *, int, int); + +extern void mtext__adjust_plist_for_insert (MText *, int, int, + struct MTextPlist *); + +extern void mtext__adjust_plist_for_change (MText *mt, int pos, + int len1, int len2); + +extern void dump_textplist (struct MTextPlist *plist, int indent); + +#endif /* _M17N_TEXTPROP_H_ */