From: Constantin Kaplinsky Date: Thu, 25 May 2006 05:04:46 +0000 (+0000) Subject: Migrating to new directory structure adopted from the RealVNC's source tree. More... X-Git-Tag: v0.0.90~384^2~282 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=b30ae7facbdf8273f34f5d67d3d2e9c81db75576;p=tigervnc.git Migrating to new directory structure adopted from the RealVNC's source tree. More changes will follow. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@590 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- diff --git a/unix/ABOUT-NLS b/unix/ABOUT-NLS new file mode 100644 index 00000000..2f50c669 --- /dev/null +++ b/unix/ABOUT-NLS @@ -0,0 +1,768 @@ +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 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 at translations should 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. + +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'. + +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 GNU `gettext' own +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 be not what is 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 have usually 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. + +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. 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 country 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. + +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://www.iro.umontreal.ca/contrib/po/HTML/', in the "National 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 `translation@iro.umontreal.ca' 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 skill are praised more than +programming skill, here. + +Available Packages +================== + +Languages are not equally supported in all packages. The following +matrix shows the current state of internationalization, as of January +2004. 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 da de el en en_GB eo es + +----------------------------------------------------+ + a2ps | [] [] [] [] | + aegis | () | + ant-phone | () | + anubis | | + ap-utils | | + aspell | [] | + bash | [] [] [] [] | + batchelor | | + bfd | [] [] | + binutils | [] [] | + bison | [] [] [] | + bluez-pin | [] [] [] | + clisp | | + clisp | [] [] [] | + console-tools | [] [] | + coreutils | [] [] [] [] | + cpio | [] [] [] | + darkstat | [] () [] | + diffutils | [] [] [] [] [] [] [] | + e2fsprogs | [] [] [] | + enscript | [] [] [] [] | + error | [] [] [] [] [] | + fetchmail | [] () [] [] [] [] | + fileutils | [] [] [] | + findutils | [] [] [] [] [] [] [] | + flex | [] [] [] [] | + fslint | | + gas | [] | + gawk | [] [] [] [] | + gbiff | [] | + gcal | [] | + gcc | [] [] | + gettext | [] [] [] [] [] | + gettext-examples | [] [] [] [] | + gettext-runtime | [] [] [] [] [] | + gettext-tools | [] [] [] | + gimp-print | [] [] [] [] [] | + gliv | | + glunarclock | [] [] | + gnubiff | [] | + gnucash | [] () [] [] | + gnucash-glossary | [] () [] | + gnupg | [] () [] [] [] [] | + gpe-aerial | [] | + gpe-beam | [] [] | + gpe-calendar | [] [] | + gpe-clock | [] [] | + gpe-conf | [] [] | + gpe-contacts | [] [] | + gpe-edit | [] | + gpe-go | [] | + gpe-login | [] [] | + gpe-ownerinfo | [] [] | + gpe-sketchbook | [] [] | + gpe-su | [] [] | + gpe-taskmanager | [] [] | + gpe-timesheet | [] | + gpe-today | [] [] | + gpe-todo | [] [] | + gphoto2 | [] [] [] [] | + gprof | [] [] [] | + gpsdrive | () () () | + gramadoir | [] | + grep | [] [] [] [] [] [] | + gretl | [] | + gtick | [] () | + hello | [] [] [] [] [] [] | + id-utils | [] [] | + indent | [] [] [] [] | + iso_3166 | [] [] [] [] [] [] [] [] [] [] | + iso_3166_1 | [] [] [] [] [] [] | + iso_3166_2 | | + iso_3166_3 | [] | + iso_4217 | [] [] [] [] | + iso_639 | | + jpilot | [] [] [] | + jtag | | + jwhois | [] | + kbd | [] [] [] [] [] | + latrine | () | + ld | [] [] | + libc | [] [] [] [] [] [] | + libgpewidget | [] [] | + libiconv | [] [] [] [] [] | + lifelines | [] () | + lilypond | [] | + lingoteach | | + lingoteach_lessons | () () | + lynx | [] [] [] [] | + m4 | [] [] [] [] | + mailutils | [] [] | + make | [] [] [] | + man-db | [] () [] [] () | + minicom | [] [] [] | + mysecretdiary | [] [] [] | + nano | [] () [] [] [] | + nano_1_0 | [] () [] [] [] | + opcodes | [] | + parted | [] [] [] [] [] | + ptx | [] [] [] [] [] | + python | | + radius | [] | + recode | [] [] [] [] [] [] [] | + rpm | [] [] | + screem | | + scrollkeeper | [] [] [] [] [] [] | + sed | [] [] [] [] [] [] | + sh-utils | [] [] [] | + shared-mime-info | | + sharutils | [] [] [] [] [] [] | + silky | () | + skencil | [] () [] | + sketch | [] () [] | + soundtracker | [] [] [] | + sp | [] | + tar | [] [] [] [] | + texinfo | [] [] [] | + textutils | [] [] [] [] | + tin | () () | + tp-robot | | + tuxpaint | [] [] [] [] [] [] [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux | [] [] [] [] [] | + vorbis-tools | [] [] [] [] | + wastesedge | () | + wdiff | [] [] [] [] | + wget | [] [] [] [] [] [] | + xchat | [] [] [] [] | + xfree86_xkb_xml | [] [] | + xpad | [] | + +----------------------------------------------------+ + af am ar az be bg bs ca cs da de el en en_GB eo es + 4 0 0 1 9 4 1 40 41 60 78 17 1 5 13 68 + + et eu fa fi fr ga gl he hr hu id is it ja ko lg + +-------------------------------------------------+ + a2ps | [] [] [] () () | + aegis | | + ant-phone | [] | + anubis | [] | + ap-utils | [] | + aspell | [] [] | + bash | [] [] | + batchelor | [] [] | + bfd | [] | + binutils | [] [] | + bison | [] [] [] [] | + bluez-pin | [] [] [] [] [] | + clisp | | + clisp | [] | + console-tools | | + coreutils | [] [] [] [] [] [] | + cpio | [] [] [] [] | + darkstat | () [] [] [] | + diffutils | [] [] [] [] [] [] [] | + e2fsprogs | | + enscript | [] [] | + error | [] [] [] [] | + fetchmail | [] | + fileutils | [] [] [] [] [] [] | + findutils | [] [] [] [] [] [] [] [] [] [] [] | + flex | [] [] [] | + fslint | [] | + gas | [] | + gawk | [] [] [] | + gbiff | [] | + gcal | [] | + gcc | [] | + gettext | [] [] [] | + gettext-examples | [] [] | + gettext-runtime | [] [] [] [] [] | + gettext-tools | [] [] [] | + gimp-print | [] [] | + gliv | () | + glunarclock | [] [] [] [] | + gnubiff | [] | + gnucash | () [] | + gnucash-glossary | [] | + gnupg | [] [] [] [] [] [] [] | + gpe-aerial | [] | + gpe-beam | [] | + gpe-calendar | [] [] [] | + gpe-clock | [] | + gpe-conf | [] | + gpe-contacts | [] [] | + gpe-edit | [] [] | + gpe-go | [] | + gpe-login | [] [] | + gpe-ownerinfo | [] [] [] | + gpe-sketchbook | [] | + gpe-su | [] | + gpe-taskmanager | [] | + gpe-timesheet | [] [] [] | + gpe-today | [] [] | + gpe-todo | [] [] | + gphoto2 | [] [] [] | + gprof | [] [] | + gpsdrive | () () () | + gramadoir | [] [] | + grep | [] [] [] [] [] [] [] [] [] [] [] | + gretl | [] [] | + gtick | [] [] [] | + hello | [] [] [] [] [] [] [] [] [] [] [] [] [] | + id-utils | [] [] [] [] | + indent | [] [] [] [] [] [] [] [] [] | + iso_3166 | [] [] [] [] [] [] [] | + iso_3166_1 | [] [] [] [] [] | + iso_3166_2 | | + iso_3166_3 | | + iso_4217 | [] [] [] [] [] [] | + iso_639 | | + jpilot | [] () | + jtag | [] | + jwhois | [] [] [] [] | + kbd | [] | + latrine | [] | + ld | [] | + libc | [] [] [] [] [] [] | + libgpewidget | [] [] [] [] | + libiconv | [] [] [] [] [] [] [] [] [] | + lifelines | () | + lilypond | [] | + lingoteach | [] [] | + lingoteach_lessons | | + lynx | [] [] [] [] | + m4 | [] [] [] [] | + mailutils | | + make | [] [] [] [] [] [] | + man-db | () () | + minicom | [] [] [] [] | + mysecretdiary | [] [] | + nano | [] [] [] [] | + nano_1_0 | [] [] [] [] | + opcodes | [] | + parted | [] [] [] | + ptx | [] [] [] [] [] [] [] | + python | | + radius | [] | + recode | [] [] [] [] [] [] | + rpm | [] [] | + screem | | + scrollkeeper | [] | + sed | [] [] [] [] [] [] [] [] [] | + sh-utils | [] [] [] [] [] [] [] | + shared-mime-info | [] [] [] | + sharutils | [] [] [] [] [] | + silky | () [] () () | + skencil | [] | + sketch | [] | + soundtracker | [] [] | + sp | [] () | + tar | [] [] [] [] [] [] [] [] [] | + texinfo | [] [] [] [] | + textutils | [] [] [] [] [] [] | + tin | [] () | + tp-robot | [] | + tuxpaint | [] [] [] [] [] [] [] [] [] | + unicode-han-tra... | | + unicode-transla... | [] [] | + util-linux | [] [] [] [] () [] | + vorbis-tools | [] | + wastesedge | () | + wdiff | [] [] [] [] [] [] | + wget | [] [] [] [] [] [] [] | + xchat | [] [] [] | + xfree86_xkb_xml | [] [] | + xpad | [] [] | + +-------------------------------------------------+ + et eu fa fi fr ga gl he hr hu id is it ja ko lg + 22 2 1 26 106 28 24 8 10 41 33 1 26 33 12 0 + + lt lv mk mn ms mt nb nl nn no nso pl pt pt_BR ro ru + +-----------------------------------------------------+ + a2ps | [] [] () () [] [] [] | + aegis | () () () | + ant-phone | [] [] | + anubis | [] [] [] [] [] [] | + ap-utils | [] () [] | + aspell | [] | + bash | [] [] [] | + batchelor | [] | + bfd | [] | + binutils | [] | + bison | [] [] [] [] [] | + bluez-pin | [] [] [] | + clisp | | + clisp | [] | + console-tools | [] | + coreutils | [] [] | + cpio | [] [] [] [] [] | + darkstat | [] [] [] [] | + diffutils | [] [] [] [] [] [] | + e2fsprogs | [] | + enscript | [] [] [] [] | + error | [] [] [] | + fetchmail | [] [] () [] | + fileutils | [] [] [] | + findutils | [] [] [] [] [] | + flex | [] [] [] [] | + fslint | [] [] | + gas | | + gawk | [] [] [] | + gbiff | [] [] | + gcal | | + gcc | | + gettext | [] [] [] | + gettext-examples | [] [] [] | + gettext-runtime | [] [] [] [] | + gettext-tools | [] [] | + gimp-print | [] | + gliv | [] [] [] | + glunarclock | [] [] [] [] | + gnubiff | [] | + gnucash | [] [] () [] | + gnucash-glossary | [] [] | + gnupg | [] | + gpe-aerial | [] [] [] [] | + gpe-beam | [] [] [] [] | + gpe-calendar | [] [] [] [] | + gpe-clock | [] [] [] [] | + gpe-conf | [] [] [] [] | + gpe-contacts | [] [] [] [] | + gpe-edit | [] [] [] [] | + gpe-go | [] [] [] | + gpe-login | [] [] [] [] | + gpe-ownerinfo | [] [] [] [] | + gpe-sketchbook | [] [] [] [] | + gpe-su | [] [] [] [] | + gpe-taskmanager | [] [] [] [] | + gpe-timesheet | [] [] [] [] | + gpe-today | [] [] [] [] | + gpe-todo | [] [] [] [] | + gphoto2 | [] | + gprof | [] [] | + gpsdrive | () () [] | + gramadoir | () [] | + grep | [] [] [] [] [] | + gretl | | + gtick | [] [] [] | + hello | [] [] [] [] [] [] [] [] [] [] | + id-utils | [] [] [] [] | + indent | [] [] [] [] | + iso_3166 | [] [] [] | + iso_3166_1 | [] [] | + iso_3166_2 | | + iso_3166_3 | [] | + iso_4217 | [] [] [] [] [] [] [] [] | + iso_639 | [] | + jpilot | () () | + jtag | | + jwhois | [] [] [] [] () | + kbd | [] [] [] | + latrine | [] | + ld | | + libc | [] [] [] [] | + libgpewidget | [] [] [] | + libiconv | [] [] [] [] [] | + lifelines | | + lilypond | | + lingoteach | | + lingoteach_lessons | | + lynx | [] [] [] | + m4 | [] [] [] [] [] | + mailutils | [] [] [] | + make | [] [] [] [] | + man-db | [] | + minicom | [] [] [] [] | + mysecretdiary | [] [] [] | + nano | [] [] [] [] [] | + nano_1_0 | [] [] [] [] [] [] | + opcodes | [] [] | + parted | [] [] [] [] | + ptx | [] [] [] [] [] [] [] [] | + python | | + radius | [] [] | + recode | [] [] [] [] | + rpm | [] [] [] | + screem | | + scrollkeeper | [] [] [] [] [] | + sed | [] [] [] | + sh-utils | [] [] | + shared-mime-info | [] [] | + sharutils | [] [] | + silky | () | + skencil | [] [] | + sketch | [] [] | + soundtracker | | + sp | | + tar | [] [] [] [] [] [] | + texinfo | [] [] [] [] | + textutils | [] [] | + tin | | + tp-robot | [] | + tuxpaint | [] [] [] [] [] [] [] [] | + unicode-han-tra... | | + unicode-transla... | | + util-linux | [] [] [] | + vorbis-tools | [] [] [] | + wastesedge | | + wdiff | [] [] [] [] [] | + wget | [] [] [] | + xchat | [] [] [] | + xfree86_xkb_xml | [] [] | + xpad | [] [] | + +-----------------------------------------------------+ + lt lv mk mn ms mt nb nl nn no nso pl pt pt_BR ro ru + 1 2 0 3 12 0 10 69 6 7 1 40 26 36 76 63 + + sk sl sr sv ta th tr uk ven vi wa xh zh_CN zh_TW zu + +-----------------------------------------------------+ + a2ps | [] [] [] [] | 16 + aegis | | 0 + ant-phone | | 3 + anubis | [] [] | 9 + ap-utils | () | 3 + aspell | | 4 + bash | | 9 + batchelor | | 3 + bfd | [] [] | 6 + binutils | [] [] [] | 8 + bison | [] [] | 14 + bluez-pin | [] [] [] | 14 + clisp | | 0 + clisp | | 5 + console-tools | | 3 + coreutils | [] [] [] [] | 16 + cpio | [] [] | 14 + darkstat | [] [] [] () () | 12 + diffutils | [] [] [] | 23 + e2fsprogs | [] [] | 6 + enscript | [] [] | 12 + error | [] [] [] | 15 + fetchmail | [] [] | 11 + fileutils | [] [] [] [] [] | 17 + findutils | [] [] [] [] [] [] | 29 + flex | [] [] | 13 + fslint | | 3 + gas | [] | 3 + gawk | [] [] | 12 + gbiff | | 4 + gcal | [] [] | 4 + gcc | [] | 4 + gettext | [] [] [] [] [] | 16 + gettext-examples | [] [] [] [] [] | 14 + gettext-runtime | [] [] [] [] [] [] [] [] | 22 + gettext-tools | [] [] [] [] [] [] | 14 + gimp-print | [] [] | 10 + gliv | | 3 + glunarclock | [] [] [] | 13 + gnubiff | | 3 + gnucash | [] [] | 9 + gnucash-glossary | [] [] [] | 8 + gnupg | [] [] [] [] | 17 + gpe-aerial | [] | 7 + gpe-beam | [] | 8 + gpe-calendar | [] [] [] [] | 13 + gpe-clock | [] [] [] | 10 + gpe-conf | [] [] | 9 + gpe-contacts | [] [] [] | 11 + gpe-edit | [] [] [] [] [] | 12 + gpe-go | | 5 + gpe-login | [] [] [] [] [] | 13 + gpe-ownerinfo | [] [] [] [] | 13 + gpe-sketchbook | [] [] | 9 + gpe-su | [] [] [] | 10 + gpe-taskmanager | [] [] [] | 10 + gpe-timesheet | [] [] [] [] | 12 + gpe-today | [] [] [] [] [] | 13 + gpe-todo | [] [] [] [] | 12 + gphoto2 | [] [] [] | 11 + gprof | [] [] | 9 + gpsdrive | [] [] | 3 + gramadoir | [] | 5 + grep | [] [] [] [] | 26 + gretl | | 3 + gtick | | 7 + hello | [] [] [] [] [] | 34 + id-utils | [] [] | 12 + indent | [] [] [] [] | 21 + iso_3166 | [] [] [] [] [] [] [] | 27 + iso_3166_1 | [] [] [] | 16 + iso_3166_2 | | 0 + iso_3166_3 | | 2 + iso_4217 | [] [] [] [] [] [] | 24 + iso_639 | | 1 + jpilot | [] [] [] [] [] | 9 + jtag | [] | 2 + jwhois | () [] [] | 11 + kbd | [] [] | 11 + latrine | | 2 + ld | [] [] | 5 + libc | [] [] [] [] | 20 + libgpewidget | [] [] [] [] | 13 + libiconv | [] [] [] [] [] [] [] [] | 27 + lifelines | [] | 2 + lilypond | [] | 3 + lingoteach | | 2 + lingoteach_lessons | () | 0 + lynx | [] [] [] | 14 + m4 | [] [] | 15 + mailutils | | 5 + make | [] [] [] | 16 + man-db | [] | 5 + minicom | | 11 + mysecretdiary | [] [] | 10 + nano | [] [] [] [] | 17 + nano_1_0 | [] [] [] | 17 + opcodes | [] [] | 6 + parted | [] [] [] | 15 + ptx | [] [] | 22 + python | | 0 + radius | | 4 + recode | [] [] [] | 20 + rpm | [] [] | 9 + screem | [] [] | 2 + scrollkeeper | [] [] [] | 15 + sed | [] [] [] [] [] [] | 24 + sh-utils | [] [] | 14 + shared-mime-info | [] [] | 7 + sharutils | [] [] [] [] | 17 + silky | () | 3 + skencil | [] | 6 + sketch | [] | 6 + soundtracker | [] [] | 7 + sp | [] | 3 + tar | [] [] [] [] [] | 24 + texinfo | [] [] [] | 14 + textutils | [] [] [] [] | 16 + tin | | 1 + tp-robot | | 2 + tuxpaint | [] [] [] [] [] | 29 + unicode-han-tra... | | 0 + unicode-transla... | | 2 + util-linux | [] [] | 15 + vorbis-tools | | 8 + wastesedge | | 0 + wdiff | [] [] [] | 18 + wget | [] [] [] [] [] [] [] [] | 24 + xchat | [] [] [] [] [] | 15 + xfree86_xkb_xml | [] [] [] [] [] | 11 + xpad | | 5 + +-----------------------------------------------------+ + 63 teams sk sl sr sv ta th tr uk ven vi wa xh zh_CN zh_TW zu + 131 domains 47 19 28 83 0 0 59 13 1 1 11 0 22 22 0 1373 + + 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 January 2004 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://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'. + +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 +`translation@iro.umontreal.ca' to make the `.pot' files available to +the translation teams. + diff --git a/unix/Makefile.in b/unix/Makefile.in new file mode 100644 index 00000000..be38406e --- /dev/null +++ b/unix/Makefile.in @@ -0,0 +1,8 @@ + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SUBDIRS = @ZLIB_DIR@ @JPEG_DIR@ intl rdr network Xregion rfb tx x0vncserver \ + vncviewer_unix po vncpasswd @VNCCONFIG_DIR@ + +# followed by boilerplate.mk diff --git a/unix/README b/unix/README new file mode 100644 index 00000000..77871721 --- /dev/null +++ b/unix/README @@ -0,0 +1,284 @@ + +TightVNC Source Distribution for Unix platforms +=============================================== + +Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. +Copyright (C) 2000-2004 Constantin Kaplinsky. +Copyright (C) 2004-2005 Peter Astrand, Cendio AB + +This software is distributed under the GNU General Public Licence as +published by the Free Software Foundation. See the file LICENCE.TXT +for the conditions under which this software is made available. +TightVNC also contains code from other sources. See the +Acknowledgements section below, and the individual files for details +of the conditions under which they are made available. + + +There are six programs here: + + vncviewer - this is the VNC viewer, or client, program for X. + + Xvnc - this is the X VNC server - it is both a VNC server and an X server + with a "virtual" framebuffer. You normally use the vncserver script + to start Xvnc. + + vncserver - this is a wrapper script which makes starting an X VNC server + (i.e. desktop) more convenient. It is written in Perl, so to use + the script you need that. + + vncpasswd - this program allows you to change the password used to access + your X VNC desktops. The vncserver script uses this program when + you first start a VNC server. + + vncconfig - this program is used to configure and control a running instance + of Xvnc. + + x0vncserver - this is an inefficient VNC server which continuously polls any + X display, allowing it to be controlled via VNC. It is + intended mainly as a demonstration of a simple VNC server. + +In addition to these standalone programs, this distribution can also +be used to turn the native X server for a platform into a VNC server. +For X.Org servers, this is done using a module loaded at run-time. +For other X servers it requires replacing the native X server binary. + +To build this distribution you need a C++ compiler as well as a C compiler. +You also need a reasonably recent version of the X window system installed. +This comes as standard with most unix machines. If you don't have it +installed, see http://www.x.org. + +To build everything but Xvnc, do: + + % ./configure + % make + +This should build first some libraries - zlib, rdr, network, Xregion, rfb and +tx - then vncviewer, vncconfig and vncpasswd. If you already have zlib +installed on your system you can run "./configure --with-installed-zlib" if you +prefer (this is strongly advised on FreeBSD, since we've been told there are +problems otherwise). + +Building Xvnc +============= + +Building Xvnc and the VNC support for native X servers is much more complex. +If you don't need to build it, skip to the section below on installing. + +Xvnc differs from the other programs in that it is built inside the X source +tree. Unlike previous versions of Xvnc, we do not provide an X source tree +with this distribution. We have designed the distribution to be as independent +as possible of the X tree used. + +We have successfully used X.Org 6.8.2 (available from http://www.x.org/). +Note that the X tree is enormous and notoriously difficult to deal with - +building it is not for the faint-hearted! + +Once you have a copy of the X source tree, make sure it is unpacked at the top +level of this distribution, so that the xc directory of the X source tree +matches the xc of this distribution, for example: + + % tar xzf X11R6.8.2-src.tar.bz2 + +Then you must apply a patch to some files in the X source tree: + + % patch -Np0 and Jef Poskanzer . This is: + + Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved. + + Permission to use, copy, modify, and distribute this software and its + documentation for NON-COMMERCIAL or COMMERCIAL purposes and without fee + is hereby granted, provided that this copyright notice is kept intact. + + WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE + SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT + NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE + LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, + MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + + THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE + CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE + PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT + NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE + SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE + SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE + PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). WIDGET + WORKSHOP SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF + FITNESS FOR HIGH RISK ACTIVITIES. + + Copyright (C) 1996 by Jef Poskanzer . All rights + reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Visit the ACME Labs Java page for up-to-date versions of this and other + fine Java utilities: http://www.acme.com/java/ diff --git a/unix/README.hpux b/unix/README.hpux new file mode 100644 index 00000000..be0c56ae --- /dev/null +++ b/unix/README.hpux @@ -0,0 +1,39 @@ +I have managed to build Xvnc on HPUX but only with some ugly hacking of +the X tree. The X tree I used as the basis for the build is the XFree86 4.2.0 +tree. The XFree86 4.3.0 tree is unsuitable as it seems to have had some HPUX +stuff removed from it. I built using the aCC C++ compiler. + +Set the following environment variables: + + % CXX=/opt/aCC/bin/aCC + % CFLAGS="+DAportable" + % CXXFLAGS="+DAportable -AA +W749 +W740" + % BOOTSTRAPCFLAGS=-Dhpux + % export CXX CFLAGS CXXFLAGS BOOTSTRAPCFLAGS + +Build the main part of the VNC distribution as normal: + + % ./configure + % make + +Unpack the X tree and apply the patches in xc.patch: + + % gunzip -c X420src-1.tgz | tar xf - + % patch -Np0 ], + [char* cs = nl_langinfo(CODESET);], + 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 +]) +# gettext.m4 serial 28 (gettext-0.13) +dnl Copyright (C) 1995-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. +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. + +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], [no], [yes])) + define(gt_libtool_suffix_prefix, ifelse([$1], [use-libtool], [l], [])) + + 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 test "$gt_cv_func_gnugettext_libc" != "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 Set USE_NLS. + AM_NLS + + ifelse(gt_included_intl, yes, [ + BUILD_INCLUDED_LIBINTL=no + USE_INCLUDED_LIBINTL=no + ]) + LIBINTL= + LTLIBINTL= + POSUB= + + 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. + + dnl Add a version number to the cache macros. + define([gt_api_version], ifelse([$2], [need-formatstring-macros], 3, ifelse([$2], [need-ngettext], 2, 1))) + define([gt_cv_func_gnugettext_libc], [gt_cv_func_gnugettext]gt_api_version[_libc]) + define([gt_cv_func_gnugettext_libintl], [gt_cv_func_gnugettext]gt_api_version[_libintl]) + + AC_CACHE_CHECK([for GNU gettext in libc], gt_cv_func_gnugettext_libc, + [AC_TRY_LINK([#include +]ifelse([$2], [need-formatstring-macros], +[#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 +], [])[extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings;], + [bindtextdomain ("", ""); +return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_domain_bindings], + gt_cv_func_gnugettext_libc=yes, + gt_cv_func_gnugettext_libc=no)]) + + if test "$gt_cv_func_gnugettext_libc" != "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_cv_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 +]ifelse([$2], [need-formatstring-macros], +[#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 +], [])[extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias ();], + [bindtextdomain ("", ""); +return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias (0)], + gt_cv_func_gnugettext_libintl=yes, + gt_cv_func_gnugettext_libintl=no) + dnl Now see whether libintl exists and depends on libiconv. + if test "$gt_cv_func_gnugettext_libintl" != yes && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + AC_TRY_LINK([#include +]ifelse([$2], [need-formatstring-macros], +[#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 +], [])[extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias ();], + [bindtextdomain ("", ""); +return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias (0)], + [LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + gt_cv_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 test "$gt_cv_func_gnugettext_libc" = "yes" \ + || { test "$gt_cv_func_gnugettext_libintl" = "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" + LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV" + LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` + fi + + 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 "$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 test "$gt_cv_func_gnugettext_libintl" = "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 test "$gt_cv_func_gnugettext_libintl" = "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. + 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 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_MKINSTALLDIRS])dnl + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([AC_ISC_POSIX])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + AC_REQUIRE([AC_C_CONST])dnl + AC_REQUIRE([bh_C_SIGNED])dnl + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_OFF_T])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([jm_AC_TYPE_LONG_LONG])dnl + AC_REQUIRE([gt_TYPE_LONGDOUBLE])dnl + AC_REQUIRE([gt_TYPE_WCHAR_T])dnl + AC_REQUIRE([gt_TYPE_WINT_T])dnl + AC_REQUIRE([jm_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([jm_AC_HEADER_STDINT_H]) + AC_REQUIRE([gt_TYPE_INTMAX_T]) + AC_REQUIRE([gt_PRINTF_POSIX]) + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + AC_REQUIRE([jm_GLIBC21])dnl + AC_REQUIRE([gt_INTDIV0])dnl + AC_REQUIRE([jm_AC_TYPE_UINTMAX_T])dnl + AC_REQUIRE([gt_HEADER_INTTYPES_H])dnl + AC_REQUIRE([gt_INTTYPES_PRI])dnl + AC_REQUIRE([gl_XSIZE])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([argz.h limits.h locale.h nl_types.h malloc.h stddef.h \ +stdlib.h string.h unistd.h sys/param.h]) + AC_CHECK_FUNCS([asprintf fwprintf getcwd getegid geteuid getgid getuid \ +mempcpy munmap putenv setenv setlocale snprintf stpcpy strcasecmp strdup \ +strtoul tsearch wcslen __argz_count __argz_stringify __argz_next \ +__fsetlocking]) + + 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(feof_unlocked, [#include ]) + gt_CHECK_DECL(fgets_unlocked, [#include ]) + 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_ICONV + AM_LANGINFO_CODESET + if test $ac_cv_header_locale_h = yes; then + AM_LC_MESSAGES + 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.]) +]) + + +dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) +AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) +# glibc21.m4 serial 2 (fileutils-4.1.3, gettext-0.10.40) +dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +# Test for the GNU C Library, version 2.1 or newer. +# From Bruno Haible. + +AC_DEFUN([jm_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" + ] +) +# iconv.m4 serial AM4 (gettext-0.11.3) +dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +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). + + 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_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.]) + 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 +]) +# intdiv0.m4 serial 1 (gettext-0.11.3) +dnl Copyright (C) 2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +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, + [ + AC_TRY_RUN([ +#include +#include + +static void +#ifdef __cplusplus +sigfpe_handler (int sig) +#else +sigfpe_handler (sig) int sig; +#endif +{ + /* 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. + case "$host_cpu" in + alpha* | i[34567]86 | m68k | s390*) + gt_cv_int_divbyzero_sigfpe="guessing yes";; + *) + gt_cv_int_divbyzero_sigfpe="guessing no";; + esac + ]) + ]) + 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.]) +]) +# intmax.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +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([jm_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([jm_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;], 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 +]) +# inttypes.m4 serial 1 (gettext-0.11.4) +dnl Copyright (C) 1997-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Paul Eggert. + +# Define HAVE_INTTYPES_H if exists and doesn't clash with +# . + +AC_DEFUN([gt_HEADER_INTTYPES_H], +[ + AC_CACHE_CHECK([for inttypes.h], gt_cv_header_inttypes_h, + [ + AC_TRY_COMPILE( + [#include +#include ], + [], gt_cv_header_inttypes_h=yes, gt_cv_header_inttypes_h=no) + ]) + if test $gt_cv_header_inttypes_h = yes; then + AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H, 1, + [Define if exists and doesn't clash with .]) + fi +]) +# inttypes_h.m4 serial 5 (gettext-0.12) +dnl Copyright (C) 1997-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Paul Eggert. + +# Define HAVE_INTTYPES_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. + +AC_DEFUN([jm_AC_HEADER_INTTYPES_H], +[ + AC_CACHE_CHECK([for inttypes.h], jm_ac_cv_header_inttypes_h, + [AC_TRY_COMPILE( + [#include +#include ], + [uintmax_t i = (uintmax_t) -1;], + jm_ac_cv_header_inttypes_h=yes, + jm_ac_cv_header_inttypes_h=no)]) + if test $jm_ac_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 +]) +# inttypes-pri.m4 serial 1 (gettext-0.11.4) +dnl Copyright (C) 1997-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. + +# 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_REQUIRE([gt_HEADER_INTTYPES_H]) + if test $gt_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.]) + fi +]) +# isc-posix.m4 serial 2 (gettext-0.11.2) +dnl Copyright (C) 1995-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +# This file is not needed with autoconf-2.53 and newer. Remove it in 2005. + +# This test replaces the one in autoconf. +# Currently this macro should have the same name as the autoconf macro +# because gettext's gettext.m4 (distributed in the automake package) +# still uses it. Otherwise, the use in gettext.m4 makes autoheader +# give these diagnostics: +# configure.in:556: AC_TRY_COMPILE was called before AC_ISC_POSIX +# configure.in:556: AC_TRY_RUN was called before AC_ISC_POSIX + +undefine([AC_ISC_POSIX]) + +AC_DEFUN([AC_ISC_POSIX], + [ + dnl This test replaces the obsolescent AC_ISC_POSIX kludge. + AC_CHECK_LIB(cposix, strerror, [LIBS="$LIBS -lcposix"]) + ] +) +# lcmessage.m4 serial 3 (gettext-0.11.3) +dnl Copyright (C) 1995-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. +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([AM_LC_MESSAGES], +[ + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include ], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES, 1, + [Define if your file defines LC_MESSAGES.]) + fi +]) +# lib-ld.m4 serial 3 (gettext-0.13) +dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +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 +]) +# lib-link.m4 serial 4 (gettext-0.12) +dnl Copyright (C) 2001-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. + +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. +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" + ]) + LIB[]NAME="$ac_cv_lib[]Name[]_libs" + LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" + INC[]NAME="$ac_cv_lib[]Name[]_cppflags" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + 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. +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= + fi + AC_SUBST([HAVE_LIB]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + undefine([Name]) + undefine([NAME]) +]) + +dnl Determine the platform dependent parameters needed to use rpath: +dnl libext, shlibext, hardcode_libdir_flag_spec, hardcode_libdir_separator, +dnl hardcode_direct, hardcode_minus_L. +AC_DEFUN([AC_LIB_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" + libext="$acl_cv_libext" + shlibext="$acl_cv_shlibext" + hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + hardcode_direct="$acl_cv_hardcode_direct" + 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. +AC_DEFUN([AC_LIB_LINKFLAGS_BODY], +[ + define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) + 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$1-prefix], +[ --with-lib$1-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib + --without-lib$1-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/lib" + 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= + 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= + if test $use_additional = yes; then + if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then + found_dir="$additional_libdir" + found_so="$additional_libdir/lib$name.$shlibext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + else + if test -f "$additional_libdir/lib$name.$libext"; then + found_dir="$additional_libdir" + found_a="$additional_libdir/lib$name.$libext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + 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//'` + if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then + found_dir="$dir" + found_so="$dir/lib$name.$shlibext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + else + if test -f "$dir/lib$name.$libext"; then + found_dir="$dir" + found_a="$dir/lib$name.$libext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + 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/lib"; 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 "$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 "$hardcode_libdir_flag_spec" && test "$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 "$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 $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 + */lib | */lib/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` + 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*) 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/lib"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/lib"; then + if test -n "$GCC"; then + case $host_os in + linux*) 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 "$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:+$hardcode_libdir_separator}$found_dir" + done + dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl. + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$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=\"$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 +]) +# lib-prefix.m4 serial 3 (gettext-0.13) +dnl Copyright (C) 2001-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +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_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/lib" + 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*) 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/lib"; 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/lib"; 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" +]) +# longdouble.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. +dnl Test whether the compiler supports the 'long double' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_LONGDOUBLE], +[ + AC_CACHE_CHECK([for long double], gt_cv_c_long_double, + [if test "$GCC" = yes; then + gt_cv_c_long_double=yes + else + AC_TRY_COMPILE([ + /* The Stardent Vistra knows sizeof(long double), but does not support it. */ + long double foo = 0.0; + /* On Ultrix 4.3 cc, long double is 4 and double is 8. */ + int array [2*(sizeof(long double) >= sizeof(double)) - 1]; + ], , + gt_cv_c_long_double=yes, gt_cv_c_long_double=no) + fi]) + if test $gt_cv_c_long_double = yes; then + AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the 'long double' type.]) + fi +]) +# longlong.m4 serial 4 +dnl Copyright (C) 1999-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Paul Eggert. + +# Define HAVE_LONG_LONG if 'long long' works. + +AC_DEFUN([jm_AC_TYPE_LONG_LONG], +[ + AC_CACHE_CHECK([for long long], ac_cv_type_long_long, + [AC_TRY_LINK([long long ll = 1LL; int i = 63;], + [long long llmax = (long long) -1; + return ll << i | ll >> i | llmax / ll | llmax % ll;], + ac_cv_type_long_long=yes, + ac_cv_type_long_long=no)]) + if test $ac_cv_type_long_long = yes; then + AC_DEFINE(HAVE_LONG_LONG, 1, + [Define if you have the 'long long' type.]) + fi +]) +# nls.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 1995-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. +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_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) +]) + +AC_DEFUN([AM_MKINSTALLDIRS], +[ + dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly + dnl find the mkinstalldirs script in another subdir but $(top_srcdir). + dnl Try to locate it. + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + case "$ac_aux_dir" in + /*) MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" ;; + *) MKINSTALLDIRS="\$(top_builddir)/$ac_aux_dir/mkinstalldirs" ;; + esac + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + AC_SUBST(MKINSTALLDIRS) +]) +# po.m4 serial 3 (gettext-0.14) +dnl Copyright (C) 1995-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. +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. + +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_MKINSTALLDIRS])dnl + AC_REQUIRE([AM_NLS])dnl + + 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 >/dev/null 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 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 >/dev/null 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 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 >/dev/null 2>&1], :) + + dnl This could go away some day; the PATH_PROG_WITH_TEST already does it. + dnl Test whether we really found GNU msgfmt. + if test "$GMSGFMT" != ":"; then + dnl If it is no GNU msgfmt we define it as : so that the + dnl Makefiles still can work. + if $GMSGFMT --statistics /dev/null >/dev/null 2>&1 && + (if $GMSGFMT --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + : ; + else + GMSGFMT=`echo "$GMSGFMT" | sed -e 's,^.*/,,'` + AC_MSG_RESULT( + [found $GMSGFMT program is not GNU msgfmt; ignore it]) + GMSGFMT=":" + fi + fi + + dnl This could go away some day; the PATH_PROG_WITH_TEST already does it. + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is no GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >/dev/null 2>&1 && + (if $XGETTEXT --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 + : ; + else + AC_MSG_RESULT( + [found xgettext program is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + dnl Remove leftover from FreeBSD xgettext call. + rm -f messages.po + fi + + AC_OUTPUT_COMMANDS([ + 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 + 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" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assigment from automake. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + 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. + 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'` + 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 _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 +]) +# progtest.m4 serial 3 (gettext-0.12) +dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. +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. + +# 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 + 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 +]) +# signed.m4 serial 1 (gettext-0.10.40) +dnl Copyright (C) 2001-2002 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Bruno Haible. + +AC_DEFUN([bh_C_SIGNED], +[ + AC_CACHE_CHECK([for signed], bh_cv_c_signed, + [AC_TRY_COMPILE(, [signed char x;], bh_cv_c_signed=yes, bh_cv_c_signed=no)]) + if test $bh_cv_c_signed = no; then + AC_DEFINE(signed, , + [Define to empty if the C compiler doesn't support this keyword.]) + fi +]) +# size_max.m4 serial 2 +dnl Copyright (C) 2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +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]) + result= + AC_EGREP_CPP([Found it], [ +#include +#if HAVE_STDINT_H +#include +#endif +#ifdef SIZE_MAX +Found it +#endif +], result=yes) + if test -z "$result"; then + dnl Define it ourselves. Here we assume that the type 'size_t' is not wider + dnl than the type 'unsigned long'. + dnl The _AC_COMPUTE_INT macro works up to LONG_MAX, since it uses 'expr', + dnl which is guaranteed to work from LONG_MIN to LONG_MAX. + _AC_COMPUTE_INT([~(size_t)0 / 10], res_hi, + [#include ], result=?) + _AC_COMPUTE_INT([~(size_t)0 % 10], res_lo, + [#include ], result=?) + _AC_COMPUTE_INT([sizeof (size_t) <= sizeof (unsigned int)], fits_in_uint, + [#include ], result=?) + 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 + if test -z "$result"; then + if test "$fits_in_uint" = 1; then + result="$res_hi$res_lo"U + else + result="$res_hi$res_lo"UL + fi + else + dnl Shouldn't happen, but who knows... + result='~(size_t)0' + fi + fi + AC_MSG_RESULT([$result]) + if test "$result" != yes; then + AC_DEFINE_UNQUOTED([SIZE_MAX], [$result], + [Define as the maximum value of type 'size_t', if the system doesn't define it.]) + fi +]) +# stdint_h.m4 serial 3 (gettext-0.12) +dnl Copyright (C) 1997-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Paul Eggert. + +# Define HAVE_STDINT_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. + +AC_DEFUN([jm_AC_HEADER_STDINT_H], +[ + AC_CACHE_CHECK([for stdint.h], jm_ac_cv_header_stdint_h, + [AC_TRY_COMPILE( + [#include +#include ], + [uintmax_t i = (uintmax_t) -1;], + jm_ac_cv_header_stdint_h=yes, + jm_ac_cv_header_stdint_h=no)]) + if test $jm_ac_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 +]) +# uintmax_t.m4 serial 7 (gettext-0.12) +dnl Copyright (C) 1997-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +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([jm_AC_TYPE_UINTMAX_T], +[ + AC_REQUIRE([jm_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([jm_AC_HEADER_STDINT_H]) + if test $jm_ac_cv_header_inttypes_h = no && test $jm_ac_cv_header_stdint_h = no; then + AC_REQUIRE([jm_AC_TYPE_UNSIGNED_LONG_LONG]) + test $ac_cv_type_unsigned_long_long = 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 +]) +# ulonglong.m4 serial 3 +dnl Copyright (C) 1999-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl From Paul Eggert. + +# Define HAVE_UNSIGNED_LONG_LONG if 'unsigned long long' works. + +AC_DEFUN([jm_AC_TYPE_UNSIGNED_LONG_LONG], +[ + AC_CACHE_CHECK([for unsigned long long], ac_cv_type_unsigned_long_long, + [AC_TRY_LINK([unsigned long long ull = 1ULL; int i = 63;], + [unsigned long long ullmax = (unsigned long long) -1; + return ull << i | ull >> i | ullmax / ull | ullmax % ull;], + ac_cv_type_unsigned_long_long=yes, + ac_cv_type_unsigned_long_long=no)]) + if test $ac_cv_type_unsigned_long_long = yes; then + AC_DEFINE(HAVE_UNSIGNED_LONG_LONG, 1, + [Define if you have the 'unsigned long long' type.]) + fi +]) +# wchar_t.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 2002-2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +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 +]) +# wint_t.m4 serial 1 (gettext-0.12) +dnl Copyright (C) 2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +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([#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 +]) +# xsize.m4 serial 2 +dnl Copyright (C) 2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +AC_DEFUN([gl_XSIZE], +[ + dnl Prerequisites of lib/xsize.h. + AC_REQUIRE([gl_SIZE_MAX]) + AC_CHECK_HEADERS(stdint.h) +]) diff --git a/unix/boilerplate.mk b/unix/boilerplate.mk new file mode 100644 index 00000000..38f376ed --- /dev/null +++ b/unix/boilerplate.mk @@ -0,0 +1,36 @@ + +all:: + @subdirs="$(SUBDIRS)"; for d in $$subdirs; do (cd $$d; $(MAKE) $@) || exit 1; done + +clean:: + @subdirs="$(SUBDIRS)"; for d in $$subdirs; do (cd $$d; $(MAKE) $@) || exit 1; done + +clean:: + rm -f $(program) $(library) *.o + +SHELL = @SHELL@ +top_srcdir = @top_srcdir@ +top_builddir = @top_builddir@ +@SET_MAKE@ +CC = @CC@ +CFLAGS = @CFLAGS@ $(DIR_CFLAGS) +CCLD = $(CC) +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CXXLD = $(CXX) +CPPFLAGS = @CPPFLAGS@ +DEFS = @DEFS@ +ALL_CPPFLAGS = $(CPPFLAGS) $(DEFS) $(DIR_CPPFLAGS) +LIBS = @LIBS@ +LDFLAGS = @LDFLAGS@ +RANLIB = @RANLIB@ +AR = ar cq + +.SUFFIXES: +.SUFFIXES: .cxx .c .o + +.c.o: + $(CC) $(ALL_CPPFLAGS) $(CFLAGS) -o $@ -c $< + +.cxx.o: + $(CXX) $(ALL_CPPFLAGS) $(CXXFLAGS) -o $@ -c $< diff --git a/unix/bootstrap b/unix/bootstrap new file mode 100755 index 00000000..73979144 --- /dev/null +++ b/unix/bootstrap @@ -0,0 +1,3 @@ +#!/bin/sh +rm -rf autom4te.cache +autoreconf -i diff --git a/unix/config.guess b/unix/config.guess new file mode 100644 index 00000000..dd1688b7 --- /dev/null +++ b/unix/config.guess @@ -0,0 +1,1459 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + +timestamp='2004-06-11' + +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# 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 Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +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 (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +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 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # 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 -q "$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 ;' + +# 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 + +# 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 tupples: *-*-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=`(/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 ;; + *) 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*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + 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 + # 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/[-_].*/\./'` + ;; + 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}" + exit 0 ;; + amd64:OpenBSD:*:*) + echo x86_64-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + cats:OpenBSD:*:*) + echo arm-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + luna88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mipseb-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit 0 ;; + macppc:MirBSD:*:*) + echo powerppc-unknown-mirbsd${UNAME_RELEASE} + exit 0 ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit 0 ;; + 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'` + exit 0 ;; + Alpha*:OpenVMS:*:*) + echo alpha-hp-vms + exit 0 ;; + 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 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + 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 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit 0 ;; + DRS?6000:UNIX_SV:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7 && exit 0 ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + 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 0 ;; + 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 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + 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 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + # 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 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + 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 \ + && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && exit 0 + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + 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 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????: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 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + 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 0 ;; + *: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 + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 + echo rs6000-ibm-aix3.2.5 + 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 0 ;; + *:AIX:*:[45]) + 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/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 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 + # avoid double evaluation of $set_cc_for_build + test -n "$CC_FOR_BUILD" || eval $set_cc_for_build + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 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 && $dummy && exit 0 + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + 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 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + *:UNICOS/mp:*:*) + echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + 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 0 ;; + 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 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + # Determine whether the default compiler uses glibc. + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #if __GLIBC__ >= 2 + LIBC=gnu + #else + LIBC= + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + # GNU/KFreeBSD systems have a "k" prefix to indicate we are using + # FreeBSD's kernel, but not the complete OS. + case ${LIBC} in gnu) kernel_only='k' ;; esac + echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + x86:Interix*:[34]*) + echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' + exit 0 ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit 0 ;; + 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 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + *: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/[-(].*//'`-gnu + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #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-gnu" && exit 0 + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #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-gnu" && exit 0 + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + 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 ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + 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-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + 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 0 ;; + 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 0 ;; + 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 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + 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 0 ;; + i*86:*:5:[78]*) + 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 0 ;; + 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 0 ;; + 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 i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + 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 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit 0 ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit 0 ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 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) + 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 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *: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 0 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + 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 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + case `uname -p` in + *86) UNAME_PROCESSOR=i686 ;; + powerpc) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *: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 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *: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 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit 0 ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +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/unix/config.h b/unix/config.h new file mode 100644 index 00000000..e69de29b diff --git a/unix/config.rpath b/unix/config.rpath new file mode 100755 index 00000000..4db13e50 --- /dev/null +++ b/unix/config.rpath @@ -0,0 +1,548 @@ +#! /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-2003 Free Software Foundation, Inc. +# Taken from GNU libtool, 2001 +# Originally by Gordon Matzigkeit , 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 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# 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. +# +# 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 M$VC, +# 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 AC_LIBTOOL_PROG_COMPILER_PIC. + +wl= +if test "$GCC" = yes; then + wl='-Wl,' +else + case "$host_os" in + aix*) + wl='-Wl,' + ;; + mingw* | pw32* | os2*) + ;; + hpux9* | hpux10* | hpux11*) + wl='-Wl,' + ;; + irix5* | irix6* | nonstopux*) + wl='-Wl,' + ;; + newsos6) + ;; + linux*) + case $CC in + icc|ecc) + wl='-Wl,' + ;; + ccc) + wl='-Wl,' + ;; + esac + ;; + osf3* | osf4* | osf5*) + wl='-Wl,' + ;; + sco3.2v5*) + ;; + solaris*) + wl='-Wl,' + ;; + sunos4*) + wl='-Qoption ld ' + ;; + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + wl='-Wl,' + ;; + sysv4*MP*) + ;; + 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 + ;; + openbsd*) + with_gnu_ld=no + ;; +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + 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 can 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 + ;; + netbsd*) + ;; + solaris* | sysv5*) + 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 + ;; + 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" = yes; then + # 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' + 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 + hardcode_direct=yes + 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 + ;; + bsdi4*) + ;; + 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*) + if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then + hardcode_direct=no + 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*) + 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* | hpux11*) + if test "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=no + ;; + ia64*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=no + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + *) + 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 + ;; + 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*) + 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 + ;; + 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=: + ;; + sco3.2v5*) + ;; + 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.2uw2*) + hardcode_direct=yes + hardcode_minus_L=no + ;; + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) + ;; + sysv5*) + hardcode_libdir_flag_spec= + ;; + 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. +libname_spec='lib$name' +case "$host_os" in + aix3*) + ;; + aix4* | aix5*) + ;; + amigaos*) + ;; + beos*) + ;; + bsdi4*) + ;; + cygwin* | mingw* | pw32*) + shrext=.dll + ;; + darwin* | rhapsody*) + shrext=.dylib + ;; + dgux*) + ;; + freebsd1*) + ;; + freebsd*) + ;; + gnu*) + ;; + hpux9* | hpux10* | hpux11*) + case "$host_cpu" in + ia64*) + shrext=.so + ;; + hppa*64*) + shrext=.sl + ;; + *) + shrext=.sl + ;; + esac + ;; + irix5* | irix6* | nonstopux*) + 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*) + ;; + netbsd*) + ;; + newsos6) + ;; + nto-qnx) + ;; + openbsd*) + ;; + os2*) + libname_spec='$name' + shrext=.dll + ;; + osf3* | osf4* | osf5*) + ;; + sco3.2v5*) + ;; + solaris*) + ;; + sunos4*) + ;; + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + ;; + sysv4*MP*) + ;; + uts4*) + ;; +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_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` + +sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# 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. + +# 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 (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +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 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # 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 0;; + + * ) + 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-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ + kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + 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) + os= + basic_machine=$1 + ;; + -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 + ;; + -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/'` + ;; + -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*) + 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 \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32r | m32rle | m68000 | m68k | m88k | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | msp430 \ + | ns16k | ns32k \ + | openrisc | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # 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-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | msp430-* \ + | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ + | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # 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 + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + 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 + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + 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 + ;; + 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'm not sure what "Sysv32" means. Should this be sysv3.2? + 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 + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + 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 + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + 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 + ;; + nv1) + basic_machine=nv1-cray + os=-unicosmp + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + 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 + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + 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) basic_machine=powerpc-unknown + ;; + ppc-*) 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 + ;; + 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 + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + 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 + ;; + 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 + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + 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 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-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 + ;; + 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 + ;; + sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b) + 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. + -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* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ + | -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* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -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*) + # 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* \ + | -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 + ;; + -kaos*) + os=-kaos + ;; + -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 + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + 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 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + 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 + ;; + *-ibm) + os=-aix + ;; + *-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 + ;; + -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 0 + +# 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/unix/configure b/unix/configure new file mode 100755 index 00000000..564099ab --- /dev/null +++ b/unix/configure @@ -0,0 +1,13054 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.59. +# +# Copyright (C) 2003 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 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+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; 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 + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# 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 + +# 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 + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + 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 + + ;; + 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 + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # 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 sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# 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'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="vncviewer_unix/vncviewer.cxx" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS PACKAGE VERSION CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX RANLIB ac_ct_RANLIB SET_MAKE MITSHM_DEFINE CXXCPP X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS ZLIB_DIR ZLIB_INCLUDE ZLIB_LIB JPEG_DIR JPEG_INCLUDE JPEG_LIB VNCCONFIG_DIR XTEST_DEFINE XTEST_LIB READDISPLAY_DEFINE VSNPRINTF_DEFINE STRCASECMP_DEFINE STRNCASECMP_DEFINE INET_LIB SOCKLEN_T_DEFINE INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA MKINSTALLDIRS USE_NLS MSGFMT GMSGFMT XGETTEXT MSGMERGE build build_cpu build_vendor build_os host host_cpu host_vendor host_os EGREP ALLOCA GLIBC21 HAVE_POSIX_PRINTF HAVE_ASPRINTF HAVE_SNPRINTF HAVE_WPRINTF LIBICONV LTLIBICONV INTLBISON BUILD_INCLUDED_LIBINTL USE_INCLUDED_LIBINTL CATOBJEXT DATADIRNAME INSTOBJEXT GENCAT INTLOBJS INTL_LIBTOOL_SUFFIX_PREFIX INTLLIBS LIBINTL LTLIBINTL POSUB LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# 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. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +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 + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -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 | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$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 ;; + + -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 ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + 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 ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -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_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=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 ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + 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'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +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 + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + 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 + + +# 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 its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + 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 + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CXX_set=${CXX+set} +ac_env_CXX_value=$CXX +ac_cv_env_CXX_set=${CXX+set} +ac_cv_env_CXX_value=$CXX +ac_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_env_CXXFLAGS_value=$CXXFLAGS +ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_cv_env_CXXFLAGS_value=$CXXFLAGS +ac_env_CXXCPP_set=${CXXCPP+set} +ac_env_CXXCPP_value=$CXXCPP +ac_cv_env_CXXCPP_set=${CXXCPP+set} +ac_cv_env_CXXCPP_value=$CXXCPP + +# +# 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 this package 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 \`..'] + +_ACEOF + + cat <<_ACEOF +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] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --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] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +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 + + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-vncconfig build the vncconfig utility (assumed by default), + use --disable-vncconfig to skip building vncconfig + --disable-nls do not use Native Language Support + --disable-rpath do not hardcode runtime library paths + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-x use the X Window System + --with-installed-zlib use the version of zlib which is installed on the + system instead of the one distributed with VNC + --with-installed-jpeg use the version of jpeg which is installed on the + system instead of the one distributed with VNC + --with-gnu-ld assume the C compiler uses GNU ld default=no + --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 + +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 + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CXXCPP C++ preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style 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 + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF + +Copyright (C) 2003 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 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +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` +hostinfo = `(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=. + echo "PATH: $as_dir" +done + +} >&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_sep= +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=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$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 + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export 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: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >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 + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + 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. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; 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,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +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 + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`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. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +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 + + + + + + + + + + + + + + + + + + + + +PACKAGE=tightvnc +VERSION=1.5.0 +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + + + + +ac_cv_prog_cc_g=no +ac_cv_prog_cxx_g=no + +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_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" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +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 + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + 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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out 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. +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; 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 | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$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 +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* 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 -std1 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 -std1. */ +int osf4_cc_array ['\x00' == 0 ? 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 +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext 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 + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC + 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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CXX" && break +done +test -n "$ac_ct_CXX" || ac_ct_CXX="g++" + + CXX=$ac_ct_CXX +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +CXXFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cxx_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +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 + +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="$(MAKE)"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +case "`(uname -sr) 2>/dev/null`" in +"SunOS 5"*) + SOLARIS=yes + USE_MITSHM=yes + USE_SUN_OVL=yes + ;; +"Linux"*) + LINUX=yes + USE_MITSHM=yes + ;; +"IRIX 6"*) + X_LIBS="-L/usr/lib32" + USE_MITSHM=yes + USE_READDISPLAY=yes + ;; +"LynxOS 2"*) + SJLJ_EXCEPTIONS=yes + ;; +esac + +if test "$USE_MITSHM" = yes; then + MITSHM_DEFINE="-DHAVE_MITSHM" +fi + + +if test "$GCC" = yes; then + CFLAGS="$CFLAGS -Wall" + if test "$SOLARIS" = yes; then + CFLAGS="$CFLAGS -Wno-unknown-pragmas -Wno-implicit-int" + fi +fi +if test "$GXX" = yes; then + CXXFLAGS="$CXXFLAGS -Wall" + if test "$SOLARIS" = yes; then + CXXFLAGS="$CXXFLAGS -Wno-unknown-pragmas -fpermissive" + fi + if test "$SJLJ_EXCEPTIONS" = yes; then + CXXFLAGS="$CXXFLAGS -fsjlj-exceptions" + fi +fi + + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6 +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6 +ac_preproc_ok=false +for ac_cxx_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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +echo "$as_me:$LINENO: checking for X" >&5 +echo $ECHO_N "checking for X... $ECHO_C" >&6 + + +# Check whether --with-x or --without-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 + if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then + # Both variables are already set. + have_x=yes + else + if test "${ac_cv_have_x+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 -fr conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + # Make sure to not put "make" in the Imakefile rules, since we grep it out. + cat >Imakefile <<'_ACEOF' +acfindx: + @echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"' +_ACEOF + if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering...", which would confuse us. + eval `${MAKE-make} acfindx 2>/dev/null | grep -v make` + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl; 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) ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /lib) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -fr 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/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/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 Intrinsic.h. + # First, try using that file with no special directory specified. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # We can compile using X headers with no special include directory. +ac_x_includes= +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Intrinsic.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi +rm -f conftest.err 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="-lXt $LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +XtMalloc (0) + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +LIBS=$ac_save_LIBS +for ac_dir in `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; do + if test -r $ac_dir/libXt.$ac_extension; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +if test "$ac_x_includes" = no || test "$ac_x_libraries" = no; then + # Didn't find X anywhere. Cache the known absence of X. + ac_cv_have_x="have_x=no" +else + # 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" +fi +fi + + fi + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + echo "$as_me:$LINENO: result: $have_x" >&5 +echo "${ECHO_T}$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" + echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 +echo "${ECHO_T}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. + +cat >>confdefs.h <<\_ACEOF +#define X_DISPLAY_MISSING 1 +_ACEOF + + 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 . . . . + case `(uname -sr) 2>/dev/null` in + "SunOS 5"*) + echo "$as_me:$LINENO: checking whether -R must be followed by a space" >&5 +echo $ECHO_N "checking whether -R must be followed by a space... $ECHO_C" >&6 + ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_R_nospace=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_R_nospace=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test $ac_R_nospace = yes; then + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + X_LIBS="$X_LIBS -R$x_libraries" + else + LIBS="$ac_xsave_LIBS -R $x_libraries" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_R_space=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_R_space=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test $ac_R_space = yes; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + X_LIBS="$X_LIBS -R $x_libraries" + else + echo "$as_me:$LINENO: result: neither works" >&5 +echo "${ECHO_T}neither works" >&6 + fi + fi + LIBS=$ac_xsave_LIBS + esac + 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XOpenDisplay (); +int +main () +{ +XOpenDisplay (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet" >&5 +echo $ECHO_N "checking for dnet_ntoa in -ldnet... $ECHO_C" >&6 +if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dnet_ntoa (); +int +main () +{ +dnet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dnet_dnet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dnet_dnet_ntoa=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_lib_dnet_dnet_ntoa" >&6 +if test $ac_cv_lib_dnet_dnet_ntoa = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" +fi + + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet_stub" >&5 +echo $ECHO_N "checking for dnet_ntoa in -ldnet_stub... $ECHO_C" >&6 +if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet_stub $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dnet_ntoa (); +int +main () +{ +dnet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dnet_stub_dnet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dnet_stub_dnet_ntoa=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_lib_dnet_stub_dnet_ntoa" >&6 +if test $ac_cv_lib_dnet_stub_dnet_ntoa = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" +fi + + fi +fi +rm -f 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. + echo "$as_me:$LINENO: checking for gethostbyname" >&5 +echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6 +if test "${ac_cv_func_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define gethostbyname to an innocuous variant, in case declares gethostbyname. + For example, HP-UX 11i declares gettimeofday. */ +#define gethostbyname innocuous_gethostbyname + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char gethostbyname (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef gethostbyname + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +/* 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_gethostbyname) || defined (__stub___gethostbyname) +choke me +#else +char (*f) () = gethostbyname; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != gethostbyname; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6 + + if test $ac_cv_func_gethostbyname = no; then + echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 +echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6 +if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main () +{ +gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_nsl_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_nsl_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6 +if test $ac_cv_lib_nsl_gethostbyname = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" +fi + + if test $ac_cv_lib_nsl_gethostbyname = no; then + echo "$as_me:$LINENO: checking for gethostbyname in -lbsd" >&5 +echo $ECHO_N "checking for gethostbyname in -lbsd... $ECHO_C" >&6 +if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbsd $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main () +{ +gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_bsd_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_bsd_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_bsd_gethostbyname" >&6 +if test $ac_cv_lib_bsd_gethostbyname = yes; 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. + echo "$as_me:$LINENO: checking for connect" >&5 +echo $ECHO_N "checking for connect... $ECHO_C" >&6 +if test "${ac_cv_func_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define connect to an innocuous variant, in case declares connect. + For example, HP-UX 11i declares gettimeofday. */ +#define connect innocuous_connect + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char connect (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef connect + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect (); +/* 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_connect) || defined (__stub___connect) +choke me +#else +char (*f) () = connect; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != connect; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_connect=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 +echo "${ECHO_T}$ac_cv_func_connect" >&6 + + if test $ac_cv_func_connect = no; then + echo "$as_me:$LINENO: checking for connect in -lsocket" >&5 +echo $ECHO_N "checking for connect in -lsocket... $ECHO_C" >&6 +if test "${ac_cv_lib_socket_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $X_EXTRA_LIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char connect (); +int +main () +{ +connect (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_socket_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_socket_connect=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_socket_connect" >&5 +echo "${ECHO_T}$ac_cv_lib_socket_connect" >&6 +if test $ac_cv_lib_socket_connect = yes; then + X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" +fi + + fi + + # Guillermo Gomez says -lposix is necessary on A/UX. + echo "$as_me:$LINENO: checking for remove" >&5 +echo $ECHO_N "checking for remove... $ECHO_C" >&6 +if test "${ac_cv_func_remove+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define remove to an innocuous variant, in case declares remove. + For example, HP-UX 11i declares gettimeofday. */ +#define remove innocuous_remove + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char remove (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef remove + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char remove (); +/* 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_remove) || defined (__stub___remove) +choke me +#else +char (*f) () = remove; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != remove; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_remove=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_remove=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_remove" >&5 +echo "${ECHO_T}$ac_cv_func_remove" >&6 + + if test $ac_cv_func_remove = no; then + echo "$as_me:$LINENO: checking for remove in -lposix" >&5 +echo $ECHO_N "checking for remove in -lposix... $ECHO_C" >&6 +if test "${ac_cv_lib_posix_remove+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lposix $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char remove (); +int +main () +{ +remove (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_posix_remove=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_posix_remove=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_posix_remove" >&5 +echo "${ECHO_T}$ac_cv_lib_posix_remove" >&6 +if test $ac_cv_lib_posix_remove = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" +fi + + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + echo "$as_me:$LINENO: checking for shmat" >&5 +echo $ECHO_N "checking for shmat... $ECHO_C" >&6 +if test "${ac_cv_func_shmat+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define shmat to an innocuous variant, in case declares shmat. + For example, HP-UX 11i declares gettimeofday. */ +#define shmat innocuous_shmat + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shmat (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef shmat + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shmat (); +/* 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_shmat) || defined (__stub___shmat) +choke me +#else +char (*f) () = shmat; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != shmat; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_shmat=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_shmat=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_shmat" >&5 +echo "${ECHO_T}$ac_cv_func_shmat" >&6 + + if test $ac_cv_func_shmat = no; then + echo "$as_me:$LINENO: checking for shmat in -lipc" >&5 +echo $ECHO_N "checking for shmat in -lipc... $ECHO_C" >&6 +if test "${ac_cv_lib_ipc_shmat+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lipc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shmat (); +int +main () +{ +shmat (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_ipc_shmat=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_ipc_shmat=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_ipc_shmat" >&5 +echo "${ECHO_T}$ac_cv_lib_ipc_shmat" >&6 +if test $ac_cv_lib_ipc_shmat = yes; 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 + echo "$as_me:$LINENO: checking for IceConnectionNumber in -lICE" >&5 +echo $ECHO_N "checking for IceConnectionNumber in -lICE... $ECHO_C" >&6 +if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lICE $X_EXTRA_LIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char IceConnectionNumber (); +int +main () +{ +IceConnectionNumber (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_ICE_IceConnectionNumber=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_ICE_IceConnectionNumber=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 +echo "${ECHO_T}$ac_cv_lib_ICE_IceConnectionNumber" >&6 +if test $ac_cv_lib_ICE_IceConnectionNumber = yes; then + X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" +fi + + LDFLAGS=$ac_save_LDFLAGS + +fi + + + +# Check whether --with-installed-zlib or --without-installed-zlib was given. +if test "${with_installed_zlib+set}" = set; then + withval="$with_installed_zlib" + +fi; + +if test "$with_installed_zlib" = yes; then + echo "using installed zlib" + ZLIB_LIB=-lz +else + ZLIB_DIR=zlib + ZLIB_INCLUDE='-I$(top_srcdir)/zlib' + ZLIB_LIB='$(top_srcdir)/zlib/libz.a' + echo "configuring zlib..." + (cd zlib; ./configure) + echo "...done configuring zlib" +fi + + + + + + +# Check whether --with-installed-jpeg or --without-installed-jpeg was given. +if test "${with_installed_jpeg+set}" = set; then + withval="$with_installed_jpeg" + +fi; + +if test "$with_installed_jpeg" = yes; then + echo "using installed jpeg" + JPEG_LIB=-ljpeg +else + JPEG_DIR=jpeg/build + JPEG_INCLUDE='-I$(top_srcdir)/jpeg' + JPEG_LIB='$(top_srcdir)/jpeg/build/libjpeg.a' + echo "configuring jpeg..." + (mkdir jpeg/build; cd jpeg/build; ../configure) + echo "...done configuring jpeg" +fi + + + + + +# Check whether --enable-vncconfig or --disable-vncconfig was given. +if test "${enable_vncconfig+set}" = set; then + enableval="$enable_vncconfig" + +fi; +if test "$enable_vncconfig" = no; then + echo "vncconfig utility will not be built" + VNCCONFIG_DIR= +else + VNCCONFIG_DIR='vncconfig_unix' +fi + + +echo "$as_me:$LINENO: checking for XTestGrabControl in -lXtst" >&5 +echo $ECHO_N "checking for XTestGrabControl in -lXtst... $ECHO_C" >&6 +if test "${ac_cv_lib_Xtst_XTestGrabControl+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lXtst "$X_LIBS" -lXext -lX11 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char XTestGrabControl (); +int +main () +{ +XTestGrabControl (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_Xtst_XTestGrabControl=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_Xtst_XTestGrabControl=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_Xtst_XTestGrabControl" >&5 +echo "${ECHO_T}$ac_cv_lib_Xtst_XTestGrabControl" >&6 +if test $ac_cv_lib_Xtst_XTestGrabControl = yes; then + USE_XTEST=yes +else + USE_XTEST= +fi + +if test "$USE_XTEST" = yes; then + XTEST_DEFINE='-DHAVE_XTEST' + XTEST_LIB=-lXtst +else + echo Warning: No XTest extension, building x0vncserver view-only + XTEST_DEFINE= + XTEST_LIB= +fi + + + +if test "$USE_READDISPLAY" = yes; then + READDISPLAY_DEFINE='-DHAVE_READDISPLAY' +elif test "$USE_SUN_OVL" = yes; then + READDISPLAY_DEFINE='-DHAVE_SUN_OVL' +else + READDISPLAY_DEFINE= +fi + + +echo "$as_me:$LINENO: checking for vsnprintf" >&5 +echo $ECHO_N "checking for vsnprintf... $ECHO_C" >&6 +if test "${ac_cv_func_vsnprintf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define vsnprintf to an innocuous variant, in case declares vsnprintf. + For example, HP-UX 11i declares gettimeofday. */ +#define vsnprintf innocuous_vsnprintf + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char vsnprintf (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef vsnprintf + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char vsnprintf (); +/* 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_vsnprintf) || defined (__stub___vsnprintf) +choke me +#else +char (*f) () = vsnprintf; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != vsnprintf; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_vsnprintf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_vsnprintf=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_vsnprintf" >&5 +echo "${ECHO_T}$ac_cv_func_vsnprintf" >&6 +if test $ac_cv_func_vsnprintf = yes; then + VSNPRINTF_DEFINE='-DHAVE_VSNPRINTF' +else + VSNPRINTF_DEFINE= +fi + + + +echo "$as_me:$LINENO: checking for strcasecmp" >&5 +echo $ECHO_N "checking for strcasecmp... $ECHO_C" >&6 +if test "${ac_cv_func_strcasecmp+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define strcasecmp to an innocuous variant, in case declares strcasecmp. + For example, HP-UX 11i declares gettimeofday. */ +#define strcasecmp innocuous_strcasecmp + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char strcasecmp (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef strcasecmp + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strcasecmp (); +/* 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_strcasecmp) || defined (__stub___strcasecmp) +choke me +#else +char (*f) () = strcasecmp; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != strcasecmp; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_strcasecmp=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_strcasecmp=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_strcasecmp" >&5 +echo "${ECHO_T}$ac_cv_func_strcasecmp" >&6 +if test $ac_cv_func_strcasecmp = yes; then + STRCASECMP_DEFINE='-DHAVE_STRCASECMP' +else + STRCASECMP_DEFINE= +fi + + + +echo "$as_me:$LINENO: checking for strncasecmp" >&5 +echo $ECHO_N "checking for strncasecmp... $ECHO_C" >&6 +if test "${ac_cv_func_strncasecmp+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define strncasecmp to an innocuous variant, in case declares strncasecmp. + For example, HP-UX 11i declares gettimeofday. */ +#define strncasecmp innocuous_strncasecmp + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char strncasecmp (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef strncasecmp + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strncasecmp (); +/* 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_strncasecmp) || defined (__stub___strncasecmp) +choke me +#else +char (*f) () = strncasecmp; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != strncasecmp; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_strncasecmp=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_strncasecmp=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_strncasecmp" >&5 +echo "${ECHO_T}$ac_cv_func_strncasecmp" >&6 +if test $ac_cv_func_strncasecmp = yes; then + STRNCASECMP_DEFINE='-DHAVE_STRNCASECMP' +else + STRNCASECMP_DEFINE= +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 + + +echo "$as_me:$LINENO: checking for gethostbyname" >&5 +echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6 +if test "${ac_cv_func_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define gethostbyname to an innocuous variant, in case declares gethostbyname. + For example, HP-UX 11i declares gettimeofday. */ +#define gethostbyname innocuous_gethostbyname + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char gethostbyname (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef gethostbyname + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +/* 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_gethostbyname) || defined (__stub___gethostbyname) +choke me +#else +char (*f) () = gethostbyname; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != gethostbyname; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6 +if test $ac_cv_func_gethostbyname = yes; then + INET_LIB_REQ= +else + INET_LIB_REQ=yes +fi + +if test "$INET_LIB_REQ" = yes; then + echo "$as_me:$LINENO: checking for gethostbyname in -lbsd" >&5 +echo $ECHO_N "checking for gethostbyname in -lbsd... $ECHO_C" >&6 +if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbsd $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main () +{ +gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_bsd_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_bsd_gethostbyname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_bsd_gethostbyname" >&6 +if test $ac_cv_lib_bsd_gethostbyname = yes; then + INET_LIB=-lbsd +else + INET_LIB= +fi + +fi +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + +echo "$as_me:$LINENO: checking for socklen_t" >&5 +echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + #include +int +main () +{ +socklen_t x; +accept(0, 0, &x); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +SOCKLEN_T_DEFINE='-DVNC_SOCKLEN_T=socklen_t' +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +echo "$as_me:$LINENO: result: using int" >&5 +echo "${ECHO_T}using int" >&6 +SOCKLEN_T_DEFINE='-DVNC_SOCKLEN_T=int' +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + + +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 + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# 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. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_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 + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +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. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$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' + + + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + case "$ac_aux_dir" in + /*) MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" ;; + *) MKINSTALLDIRS="\$(top_builddir)/$ac_aux_dir/mkinstalldirs" ;; + esac + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + + + + echo "$as_me:$LINENO: checking whether NLS is requested" >&5 +echo $ECHO_N "checking whether NLS is requested... $ECHO_C" >&6 + # Check whether --enable-nls or --disable-nls was given. +if test "${enable_nls+set}" = set; then + enableval="$enable_nls" + USE_NLS=$enableval +else + USE_NLS=yes +fi; + echo "$as_me:$LINENO: result: $USE_NLS" >&5 +echo "${ECHO_T}$USE_NLS" >&6 + + + + + + +# 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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_MSGFMT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 + if $ac_dir/$ac_word --statistics /dev/null >/dev/null 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 + echo "$as_me:$LINENO: result: $MSGFMT" >&5 +echo "${ECHO_T}$MSGFMT" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_GMSGFMT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT=$ac_cv_path_GMSGFMT + +if test -n "$GMSGFMT"; then + echo "$as_me:$LINENO: result: $GMSGFMT" >&5 +echo "${ECHO_T}$GMSGFMT" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +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 + +# 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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_XGETTEXT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 + if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >/dev/null 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 + echo "$as_me:$LINENO: result: $XGETTEXT" >&5 +echo "${ECHO_T}$XGETTEXT" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + rm -f messages.po + + +# 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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_MSGMERGE+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 + if $ac_dir/$ac_word --update -q /dev/null /dev/null >/dev/null 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 + echo "$as_me:$LINENO: result: $MSGMERGE" >&5 +echo "${ECHO_T}$MSGMERGE" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + + if test "$GMSGFMT" != ":"; then + if $GMSGFMT --statistics /dev/null >/dev/null 2>&1 && + (if $GMSGFMT --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + : ; + else + GMSGFMT=`echo "$GMSGFMT" | sed -e 's,^.*/,,'` + echo "$as_me:$LINENO: result: found $GMSGFMT program is not GNU msgfmt; ignore it" >&5 +echo "${ECHO_T}found $GMSGFMT program is not GNU msgfmt; ignore it" >&6 + GMSGFMT=":" + fi + fi + + if test "$XGETTEXT" != ":"; then + if $XGETTEXT --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >/dev/null 2>&1 && + (if $XGETTEXT --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 + : ; + else + echo "$as_me:$LINENO: result: found xgettext program is not GNU xgettext; ignore it" >&5 +echo "${ECHO_T}found xgettext program is not GNU xgettext; ignore it" >&6 + XGETTEXT=":" + fi + rm -f messages.po + fi + + ac_config_commands="$ac_config_commands default-1" + + +# Make sure we can run config.sub. +$ac_config_sub sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 +echo "$as_me: error: cannot run $ac_config_sub" >&2;} + { (exit 1); exit 1; }; } + +echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6 +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_build_alias=$build_alias +test -z "$ac_cv_build_alias" && + ac_cv_build_alias=`$ac_config_guess` +test -z "$ac_cv_build_alias" && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6 +build=$ac_cv_build +build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + +echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6 +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_host_alias=$host_alias +test -z "$ac_cv_host_alias" && + ac_cv_host_alias=$ac_cv_build_alias +ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6 +host=$ac_cv_host +host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + + + echo "$as_me:$LINENO: checking for strerror in -lcposix" >&5 +echo $ECHO_N "checking for strerror in -lcposix... $ECHO_C" >&6 +if test "${ac_cv_lib_cposix_strerror+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcposix $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strerror (); +int +main () +{ +strerror (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_cposix_strerror=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_cposix_strerror=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_cposix_strerror" >&5 +echo "${ECHO_T}$ac_cv_lib_cposix_strerror" >&6 +if test $ac_cv_lib_cposix_strerror = yes; then + LIBS="$LIBS -lcposix" +fi + + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#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)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 +echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 +if test "${ac_cv_c_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset x; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *ccp; + char **p; + /* 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"; + ccp = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++ccp; + p = (char**) ccp; + ccp = (char const *const *) p; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 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 saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + } +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_const=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_const=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 +echo "${ECHO_T}$ac_cv_c_const" >&6 +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\_ACEOF +#define const +_ACEOF + +fi + + + echo "$as_me:$LINENO: checking for signed" >&5 +echo $ECHO_N "checking for signed... $ECHO_C" >&6 +if test "${bh_cv_c_signed+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +signed char x; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + bh_cv_c_signed=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +bh_cv_c_signed=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $bh_cv_c_signed" >&5 +echo "${ECHO_T}$bh_cv_c_signed" >&6 + if test $bh_cv_c_signed = no; then + +cat >>confdefs.h <<\_ACEOF +#define signed +_ACEOF + + fi + +echo "$as_me:$LINENO: checking for inline" >&5 +echo $ECHO_N "checking for inline... $ECHO_C" >&6 +if test "${ac_cv_c_inline+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_inline=$ac_kw; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 +echo "${ECHO_T}$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 + +# 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=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +echo "$as_me:$LINENO: checking for off_t" >&5 +echo $ECHO_N "checking for off_t... $ECHO_C" >&6 +if test "${ac_cv_type_off_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((off_t *) 0) + return 0; +if (sizeof (off_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_off_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_off_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5 +echo "${ECHO_T}$ac_cv_type_off_t" >&6 +if test $ac_cv_type_off_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define off_t long +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for size_t" >&5 +echo $ECHO_N "checking for size_t... $ECHO_C" >&6 +if test "${ac_cv_type_size_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((size_t *) 0) + return 0; +if (sizeof (size_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_size_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_size_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 +echo "${ECHO_T}$ac_cv_type_size_t" >&6 +if test $ac_cv_type_size_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned +_ACEOF + +fi + + + echo "$as_me:$LINENO: checking for long long" >&5 +echo $ECHO_N "checking for long long... $ECHO_C" >&6 +if test "${ac_cv_type_long_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +long long ll = 1LL; int i = 63; +int +main () +{ +long long llmax = (long long) -1; + return ll << i | ll >> i | llmax / ll | llmax % ll; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_long_long=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_long_long=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_long_long" >&5 +echo "${ECHO_T}$ac_cv_type_long_long" >&6 + if test $ac_cv_type_long_long = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LONG_LONG 1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for long double" >&5 +echo $ECHO_N "checking for long double... $ECHO_C" >&6 +if test "${gt_cv_c_long_double+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$GCC" = yes; then + gt_cv_c_long_double=yes + else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + /* The Stardent Vistra knows sizeof(long double), but does not support it. */ + long double foo = 0.0; + /* On Ultrix 4.3 cc, long double is 4 and double is 8. */ + int array [2*(sizeof(long double) >= sizeof(double)) - 1]; + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + gt_cv_c_long_double=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +gt_cv_c_long_double=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + fi +fi +echo "$as_me:$LINENO: result: $gt_cv_c_long_double" >&5 +echo "${ECHO_T}$gt_cv_c_long_double" >&6 + if test $gt_cv_c_long_double = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LONG_DOUBLE 1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for wchar_t" >&5 +echo $ECHO_N "checking for wchar_t... $ECHO_C" >&6 +if test "${gt_cv_c_wchar_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + wchar_t foo = (wchar_t)'\0'; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + gt_cv_c_wchar_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +gt_cv_c_wchar_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $gt_cv_c_wchar_t" >&5 +echo "${ECHO_T}$gt_cv_c_wchar_t" >&6 + if test $gt_cv_c_wchar_t = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_WCHAR_T 1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for wint_t" >&5 +echo $ECHO_N "checking for wint_t... $ECHO_C" >&6 +if test "${gt_cv_c_wint_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + wint_t foo = (wchar_t)'\0'; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + gt_cv_c_wint_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +gt_cv_c_wint_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $gt_cv_c_wint_t" >&5 +echo "${ECHO_T}$gt_cv_c_wint_t" >&6 + if test $gt_cv_c_wint_t = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_WINT_T 1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for inttypes.h" >&5 +echo $ECHO_N "checking for inttypes.h... $ECHO_C" >&6 +if test "${jm_ac_cv_header_inttypes_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +int +main () +{ +uintmax_t i = (uintmax_t) -1; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + jm_ac_cv_header_inttypes_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +jm_ac_cv_header_inttypes_h=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $jm_ac_cv_header_inttypes_h" >&5 +echo "${ECHO_T}$jm_ac_cv_header_inttypes_h" >&6 + if test $jm_ac_cv_header_inttypes_h = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_INTTYPES_H_WITH_UINTMAX 1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for stdint.h" >&5 +echo $ECHO_N "checking for stdint.h... $ECHO_C" >&6 +if test "${jm_ac_cv_header_stdint_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +int +main () +{ +uintmax_t i = (uintmax_t) -1; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + jm_ac_cv_header_stdint_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +jm_ac_cv_header_stdint_h=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $jm_ac_cv_header_stdint_h" >&5 +echo "${ECHO_T}$jm_ac_cv_header_stdint_h" >&6 + if test $jm_ac_cv_header_stdint_h = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STDINT_H_WITH_UINTMAX 1 +_ACEOF + + fi + + + + + echo "$as_me:$LINENO: checking for intmax_t" >&5 +echo $ECHO_N "checking for intmax_t... $ECHO_C" >&6 +if test "${gt_cv_c_intmax_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + gt_cv_c_intmax_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +gt_cv_c_intmax_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $gt_cv_c_intmax_t" >&5 +echo "${ECHO_T}$gt_cv_c_intmax_t" >&6 + if test $gt_cv_c_intmax_t = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_INTMAX_T 1 +_ACEOF + + fi + + + + echo "$as_me:$LINENO: checking whether printf() supports POSIX/XSI format strings" >&5 +echo $ECHO_N "checking whether printf() supports POSIX/XSI format strings... $ECHO_C" >&6 +if test "${gt_cv_func_printf_posix+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#if defined __NetBSD__ || 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + gt_cv_func_printf_posix=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +gt_cv_func_printf_posix=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $gt_cv_func_printf_posix" >&5 +echo "${ECHO_T}$gt_cv_func_printf_posix" >&6 + case $gt_cv_func_printf_posix in + *yes) + +cat >>confdefs.h <<\_ACEOF +#define HAVE_POSIX_PRINTF 1 +_ACEOF + + ;; + esac + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo "$as_me:$LINENO: checking for working alloca.h" >&5 +echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6 +if test "${ac_cv_working_alloca_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +char *p = (char *) alloca (2 * sizeof (int)); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_working_alloca_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_working_alloca_h=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5 +echo "${ECHO_T}$ac_cv_working_alloca_h" >&6 +if test $ac_cv_working_alloca_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ALLOCA_H 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for alloca" >&5 +echo $ECHO_N "checking for alloca... $ECHO_C" >&6 +if test "${ac_cv_func_alloca_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +int +main () +{ +char *p = (char *) alloca (1); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_alloca_works=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_alloca_works=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5 +echo "${ECHO_T}$ac_cv_func_alloca_works" >&6 + +if test $ac_cv_func_alloca_works = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ALLOCA 1 +_ACEOF + +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=alloca.$ac_objext + +cat >>confdefs.h <<\_ACEOF +#define C_ALLOCA 1 +_ACEOF + + +echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5 +echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6 +if test "${ac_cv_os_cray+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 +echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5 +echo "${ECHO_T}$ac_cv_os_cray" >&6 +if test $ac_cv_os_cray = yes; then + for ac_func in _getb67 GETB67 getb67; do + as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* 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_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + +cat >>confdefs.h <<_ACEOF +#define CRAY_STACKSEG_END $ac_func +_ACEOF + + break +fi + + done +fi + +echo "$as_me:$LINENO: checking stack direction for C alloca" >&5 +echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6 +if test "${ac_cv_c_stack_direction+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int +find_stack_direction () +{ + static char *addr = 0; + auto char dummy; + if (addr == 0) + { + addr = &dummy; + return find_stack_direction (); + } + else + return (&dummy > addr) ? 1 : -1; +} + +int +main () +{ + exit (find_stack_direction () < 0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_stack_direction=1 +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_stack_direction=-1 +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5 +echo "${ECHO_T}$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 unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_func in getpagesize +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* 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_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +echo "$as_me:$LINENO: checking for working mmap" >&5 +echo $ECHO_N "checking for working mmap... $ECHO_C" >&6 +if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 !STDC_HEADERS && !HAVE_STDLIB_H +char *malloc (); +#endif + +/* This mess was copied from the GNU getpagesize.h. */ +#if !HAVE_GETPAGESIZE +/* Assume that all systems that can run configure have sys/param.h. */ +# if !HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# if 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; + int i, pagesize; + int fd; + + pagesize = getpagesize (); + + /* First, make a file with some known garbage in it. */ + data = (char *) malloc (pagesize); + if (!data) + exit (1); + for (i = 0; i < pagesize; ++i) + *(data + i) = rand (); + umask (0); + fd = creat ("conftest.mmap", 0600); + if (fd < 0) + exit (1); + if (write (fd, data, pagesize) != pagesize) + exit (1); + close (fd); + + /* 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) + exit (1); + data2 = (char *) malloc (2 * pagesize); + if (!data2) + exit (1); + data2 += (pagesize - ((long) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + exit (1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + exit (1); + + /* 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) + exit (1); + if (read (fd, data3, pagesize) != pagesize) + exit (1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + exit (1); + close (fd); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_mmap_fixed_mapped=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5 +echo "${ECHO_T}$ac_cv_func_mmap_fixed_mapped" >&6 +if test $ac_cv_func_mmap_fixed_mapped = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MMAP 1 +_ACEOF + +fi +rm -f conftest.mmap + + + echo "$as_me:$LINENO: checking whether we are using the GNU C Library 2.1 or newer" >&5 +echo $ECHO_N "checking whether we are using the GNU C Library 2.1 or newer... $ECHO_C" >&6 +if test "${ac_cv_gnu_library_2_1+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 +echo "$as_me:$LINENO: result: $ac_cv_gnu_library_2_1" >&5 +echo "${ECHO_T}$ac_cv_gnu_library_2_1" >&6 + + GLIBC21="$ac_cv_gnu_library_2_1" + + + + + echo "$as_me:$LINENO: checking whether integer division by zero raises SIGFPE" >&5 +echo $ECHO_N "checking whether integer division by zero raises SIGFPE... $ECHO_C" >&6 +if test "${gt_cv_int_divbyzero_sigfpe+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + + # Guess based on the CPU. + case "$host_cpu" in + alpha* | i3456786 | m68k | s390*) + gt_cv_int_divbyzero_sigfpe="guessing yes";; + *) + gt_cv_int_divbyzero_sigfpe="guessing no";; + esac + +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include + +static void +#ifdef __cplusplus +sigfpe_handler (int sig) +#else +sigfpe_handler (sig) int sig; +#endif +{ + /* 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 +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + gt_cv_int_divbyzero_sigfpe=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +gt_cv_int_divbyzero_sigfpe=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + +fi +echo "$as_me:$LINENO: result: $gt_cv_int_divbyzero_sigfpe" >&5 +echo "${ECHO_T}$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 + + + + echo "$as_me:$LINENO: checking for unsigned long long" >&5 +echo $ECHO_N "checking for unsigned long long... $ECHO_C" >&6 +if test "${ac_cv_type_unsigned_long_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +unsigned long long ull = 1ULL; int i = 63; +int +main () +{ +unsigned long long ullmax = (unsigned long long) -1; + return ull << i | ull >> i | ullmax / ull | ullmax % ull; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_unsigned_long_long=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_unsigned_long_long=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_unsigned_long_long" >&5 +echo "${ECHO_T}$ac_cv_type_unsigned_long_long" >&6 + if test $ac_cv_type_unsigned_long_long = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_UNSIGNED_LONG_LONG 1 +_ACEOF + + fi + + + + + if test $jm_ac_cv_header_inttypes_h = no && test $jm_ac_cv_header_stdint_h = no; then + + test $ac_cv_type_unsigned_long_long = yes \ + && ac_type='unsigned long long' \ + || ac_type='unsigned long' + +cat >>confdefs.h <<_ACEOF +#define uintmax_t $ac_type +_ACEOF + + else + +cat >>confdefs.h <<\_ACEOF +#define HAVE_UINTMAX_T 1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for inttypes.h" >&5 +echo $ECHO_N "checking for inttypes.h... $ECHO_C" >&6 +if test "${gt_cv_header_inttypes_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + gt_cv_header_inttypes_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +gt_cv_header_inttypes_h=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $gt_cv_header_inttypes_h" >&5 +echo "${ECHO_T}$gt_cv_header_inttypes_h" >&6 + if test $gt_cv_header_inttypes_h = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_INTTYPES_H 1 +_ACEOF + + fi + + + + if test $gt_cv_header_inttypes_h = yes; then + echo "$as_me:$LINENO: checking whether the inttypes.h PRIxNN macros are broken" >&5 +echo $ECHO_N "checking whether the inttypes.h PRIxNN macros are broken... $ECHO_C" >&6 +if test "${gt_cv_inttypes_pri_broken+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#ifdef PRId32 +char *p = PRId32; +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + gt_cv_inttypes_pri_broken=no +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +gt_cv_inttypes_pri_broken=yes +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $gt_cv_inttypes_pri_broken" >&5 +echo "${ECHO_T}$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 + + fi + + + +for ac_header in stdint.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + echo "$as_me:$LINENO: checking for SIZE_MAX" >&5 +echo $ECHO_N "checking for SIZE_MAX... $ECHO_C" >&6 + result= + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 + result=yes +fi +rm -f conftest* + + if test -z "$result"; then + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +static int test_array [1 - 2 * !((~(size_t)0 / 10) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +static int test_array [1 - 2 * !((~(size_t)0 / 10) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +static int test_array [1 - 2 * !((~(size_t)0 / 10) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +static int test_array [1 - 2 * !((~(size_t)0 / 10) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo= ac_hi= +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +static int test_array [1 - 2 * !((~(size_t)0 / 10) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) res_hi=$ac_lo;; +'') result=? ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +long longval () { return ~(size_t)0 / 10; } +unsigned long ulongval () { return ~(size_t)0 / 10; } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if ((~(size_t)0 / 10) < 0) + { + long i = longval (); + if (i != (~(size_t)0 / 10)) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != (~(size_t)0 / 10)) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + res_hi=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +result=? +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +static int test_array [1 - 2 * !((~(size_t)0 % 10) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +static int test_array [1 - 2 * !((~(size_t)0 % 10) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +static int test_array [1 - 2 * !((~(size_t)0 % 10) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +static int test_array [1 - 2 * !((~(size_t)0 % 10) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo= ac_hi= +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +static int test_array [1 - 2 * !((~(size_t)0 % 10) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) res_lo=$ac_lo;; +'') result=? ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +long longval () { return ~(size_t)0 % 10; } +unsigned long ulongval () { return ~(size_t)0 % 10; } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if ((~(size_t)0 % 10) < 0) + { + long i = longval (); + if (i != (~(size_t)0 % 10)) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != (~(size_t)0 % 10)) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + res_lo=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +result=? +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +static int test_array [1 - 2 * !((sizeof (size_t) <= sizeof (unsigned int)) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=0 ac_mid=0 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +static int test_array [1 - 2 * !((sizeof (size_t) <= sizeof (unsigned int)) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +static int test_array [1 - 2 * !((sizeof (size_t) <= sizeof (unsigned int)) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=-1 ac_mid=-1 + while :; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +static int test_array [1 - 2 * !((sizeof (size_t) <= sizeof (unsigned int)) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_lo=$ac_mid; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo= ac_hi= +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +static int test_array [1 - 2 * !((sizeof (size_t) <= sizeof (unsigned int)) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_hi=$ac_mid +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_lo=`expr '(' $ac_mid ')' + 1` +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) fits_in_uint=$ac_lo;; +'') result=? ;; +esac +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +long longval () { return sizeof (size_t) <= sizeof (unsigned int); } +unsigned long ulongval () { return sizeof (size_t) <= sizeof (unsigned int); } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + exit (1); + if ((sizeof (size_t) <= sizeof (unsigned int)) < 0) + { + long i = longval (); + if (i != (sizeof (size_t) <= sizeof (unsigned int))) + exit (1); + fprintf (f, "%ld\n", i); + } + else + { + unsigned long i = ulongval (); + if (i != (sizeof (size_t) <= sizeof (unsigned int))) + exit (1); + fprintf (f, "%lu\n", i); + } + exit (ferror (f) || fclose (f) != 0); + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + fits_in_uint=`cat conftest.val` +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +result=? +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +rm -f conftest.val + if test "$fits_in_uint" = 1; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + extern size_t foo; + extern unsigned long foo; + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + fits_in_uint=0 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test -z "$result"; then + if test "$fits_in_uint" = 1; then + result="$res_hi$res_lo"U + else + result="$res_hi$res_lo"UL + fi + else + result='~(size_t)0' + fi + fi + echo "$as_me:$LINENO: result: $result" >&5 +echo "${ECHO_T}$result" >&6 + if test "$result" != yes; then + +cat >>confdefs.h <<_ACEOF +#define SIZE_MAX $result +_ACEOF + + fi + + + + +for ac_header in stdint.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + 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 or --without-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. + echo "$as_me:$LINENO: checking for ld used by GCC" >&5 +echo $ECHO_N "checking for ld used by GCC... $ECHO_C" >&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 + echo "$as_me:$LINENO: checking for GNU ld" >&5 +echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 +else + echo "$as_me:$LINENO: checking for non-GNU ld" >&5 +echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 +fi +if test "${acl_cv_path_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 + echo "$as_me:$LINENO: result: $LD" >&5 +echo "${ECHO_T}$LD" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 +echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} + { (exit 1); exit 1; }; } +echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 +echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 +if test "${acl_cv_prog_gnu_ld+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # I'd rather use --version here, but apparently some GNU ld's only accept -v. +case `$LD -v 2>&1 &5 +echo "${ECHO_T}$acl_cv_prog_gnu_ld" >&6 +with_gnu_ld=$acl_cv_prog_gnu_ld + + + + echo "$as_me:$LINENO: checking for shared library run path origin" >&5 +echo $ECHO_N "checking for shared library run path origin... $ECHO_C" >&6 +if test "${acl_cv_rpath+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 +echo "$as_me:$LINENO: result: $acl_cv_rpath" >&5 +echo "${ECHO_T}$acl_cv_rpath" >&6 + wl="$acl_cv_wl" + libext="$acl_cv_libext" + shlibext="$acl_cv_shlibext" + hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + hardcode_direct="$acl_cv_hardcode_direct" + hardcode_minus_L="$acl_cv_hardcode_minus_L" + # Check whether --enable-rpath or --disable-rpath was given. +if test "${enable_rpath+set}" = set; then + enableval="$enable_rpath" + : +else + enable_rpath=yes +fi; + + + + + + + + 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 or --without-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/lib" + fi + fi + +fi; + LIBICONV= + LTLIBICONV= + INCICONV= + 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= + if test $use_additional = yes; then + if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then + found_dir="$additional_libdir" + found_so="$additional_libdir/lib$name.$shlibext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + else + if test -f "$additional_libdir/lib$name.$libext"; then + found_dir="$additional_libdir" + found_a="$additional_libdir/lib$name.$libext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + 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 "$shlibext" && test -f "$dir/lib$name.$shlibext"; then + found_dir="$dir" + found_so="$dir/lib$name.$shlibext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + else + if test -f "$dir/lib$name.$libext"; then + found_dir="$dir" + found_a="$dir/lib$name.$libext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + 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/lib"; 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 "$hardcode_direct" = yes; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + if test -n "$hardcode_libdir_flag_spec" && test "$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 "$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 + */lib | */lib/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` + 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*) 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/lib"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/lib"; then + if test -n "$GCC"; then + case $host_os in + linux*) 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 "$hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$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=\"$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 + + + + + + + + + echo "$as_me:$LINENO: checking for ptrdiff_t" >&5 +echo $ECHO_N "checking for ptrdiff_t... $ECHO_C" >&6 +if test "${ac_cv_type_ptrdiff_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((ptrdiff_t *) 0) + return 0; +if (sizeof (ptrdiff_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_ptrdiff_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_ptrdiff_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_ptrdiff_t" >&5 +echo "${ECHO_T}$ac_cv_type_ptrdiff_t" >&6 +if test $ac_cv_type_ptrdiff_t = yes; then + : +else + +cat >>confdefs.h <<\_ACEOF +#define ptrdiff_t long +_ACEOF + + +fi + + + + + + + + + + + +for ac_header in argz.h limits.h locale.h nl_types.h malloc.h stddef.h \ +stdlib.h string.h unistd.h sys/param.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + + + + + + + + + + + + + + + + + + +for ac_func in asprintf fwprintf getcwd getegid geteuid getgid getuid \ +mempcpy munmap putenv setenv setlocale snprintf stpcpy strcasecmp strdup \ +strtoul tsearch wcslen __argz_count __argz_stringify __argz_next \ +__fsetlocking +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* 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_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + echo "$as_me:$LINENO: checking whether _snprintf is declared" >&5 +echo $ECHO_N "checking whether _snprintf is declared... $ECHO_C" >&6 +if test "${ac_cv_have_decl__snprintf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ + +#ifndef _snprintf + char *p = (char *) _snprintf; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_have_decl__snprintf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_have_decl__snprintf=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_have_decl__snprintf" >&5 +echo "${ECHO_T}$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 + + + + echo "$as_me:$LINENO: checking whether _snwprintf is declared" >&5 +echo $ECHO_N "checking whether _snwprintf is declared... $ECHO_C" >&6 +if test "${ac_cv_have_decl__snwprintf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ + +#ifndef _snwprintf + char *p = (char *) _snwprintf; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_have_decl__snwprintf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_have_decl__snwprintf=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_have_decl__snwprintf" >&5 +echo "${ECHO_T}$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 + + + + + echo "$as_me:$LINENO: checking whether feof_unlocked is declared" >&5 +echo $ECHO_N "checking whether feof_unlocked is declared... $ECHO_C" >&6 +if test "${ac_cv_have_decl_feof_unlocked+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ + +#ifndef feof_unlocked + char *p = (char *) feof_unlocked; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_have_decl_feof_unlocked=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_have_decl_feof_unlocked=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_have_decl_feof_unlocked" >&5 +echo "${ECHO_T}$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 + + + + echo "$as_me:$LINENO: checking whether fgets_unlocked is declared" >&5 +echo $ECHO_N "checking whether fgets_unlocked is declared... $ECHO_C" >&6 +if test "${ac_cv_have_decl_fgets_unlocked+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ + +#ifndef fgets_unlocked + char *p = (char *) fgets_unlocked; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_have_decl_fgets_unlocked=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_have_decl_fgets_unlocked=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_have_decl_fgets_unlocked" >&5 +echo "${ECHO_T}$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 + + + + echo "$as_me:$LINENO: checking whether getc_unlocked is declared" >&5 +echo $ECHO_N "checking whether getc_unlocked is declared... $ECHO_C" >&6 +if test "${ac_cv_have_decl_getc_unlocked+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ + +#ifndef getc_unlocked + char *p = (char *) getc_unlocked; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_have_decl_getc_unlocked=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_have_decl_getc_unlocked=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_have_decl_getc_unlocked" >&5 +echo "${ECHO_T}$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 + + + + + + + + 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 + + + echo "$as_me:$LINENO: checking for iconv" >&5 +echo $ECHO_N "checking for iconv... $ECHO_C" >&6 +if test "${am_cv_func_iconv+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + am_cv_func_iconv=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f 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 >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + am_cv_lib_iconv=yes + am_cv_func_iconv=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$am_save_LIBS" + fi + +fi +echo "$as_me:$LINENO: result: $am_cv_func_iconv" >&5 +echo "${ECHO_T}$am_cv_func_iconv" >&6 + if test "$am_cv_func_iconv" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ICONV 1 +_ACEOF + + fi + if test "$am_cv_lib_iconv" = yes; then + echo "$as_me:$LINENO: checking how to link with libiconv" >&5 +echo $ECHO_N "checking how to link with libiconv... $ECHO_C" >&6 + echo "$as_me:$LINENO: result: $LIBICONV" >&5 +echo "${ECHO_T}$LIBICONV" >&6 + else + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + + + + if test "$am_cv_func_iconv" = yes; then + echo "$as_me:$LINENO: checking for iconv declaration" >&5 +echo $ECHO_N "checking for iconv declaration... $ECHO_C" >&6 + if test "${am_cv_proto_iconv+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + am_cv_proto_iconv_arg1="" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +am_cv_proto_iconv_arg1="const" +fi +rm -f 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/( /(/'` + echo "$as_me:$LINENO: result: ${ac_t:- + }$am_cv_proto_iconv" >&5 +echo "${ECHO_T}${ac_t:- + }$am_cv_proto_iconv" >&6 + +cat >>confdefs.h <<_ACEOF +#define ICONV_CONST $am_cv_proto_iconv_arg1 +_ACEOF + + fi + + + echo "$as_me:$LINENO: checking for nl_langinfo and CODESET" >&5 +echo $ECHO_N "checking for nl_langinfo and CODESET... $ECHO_C" >&6 +if test "${am_cv_langinfo_codeset+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +char* cs = nl_langinfo(CODESET); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + am_cv_langinfo_codeset=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +am_cv_langinfo_codeset=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $am_cv_langinfo_codeset" >&5 +echo "${ECHO_T}$am_cv_langinfo_codeset" >&6 + if test $am_cv_langinfo_codeset = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LANGINFO_CODESET 1 +_ACEOF + + fi + + if test $ac_cv_header_locale_h = yes; then + + echo "$as_me:$LINENO: checking for LC_MESSAGES" >&5 +echo $ECHO_N "checking for LC_MESSAGES... $ECHO_C" >&6 +if test "${am_cv_val_LC_MESSAGES+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +return LC_MESSAGES + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + am_cv_val_LC_MESSAGES=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +am_cv_val_LC_MESSAGES=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $am_cv_val_LC_MESSAGES" >&5 +echo "${ECHO_T}$am_cv_val_LC_MESSAGES" >&6 + if test $am_cv_val_LC_MESSAGES = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LC_MESSAGES 1 +_ACEOF + + fi + + 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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_INTLBISON+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_INTLBISON="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +INTLBISON=$ac_cv_prog_INTLBISON +if test -n "$INTLBISON"; then + echo "$as_me:$LINENO: result: $INTLBISON" >&5 +echo "${ECHO_T}$INTLBISON" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$INTLBISON" && break +done + + if test -z "$INTLBISON"; then + ac_verc_fail=yes + else + echo "$as_me:$LINENO: checking version of bison" >&5 +echo $ECHO_N "checking version of bison... $ECHO_C" >&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 + echo "$as_me:$LINENO: result: $ac_prog_version" >&5 +echo "${ECHO_T}$ac_prog_version" >&6 + fi + if test $ac_verc_fail = yes; then + INTLBISON=: + fi + + + + + + + + + + + + + + + + + echo "$as_me:$LINENO: checking whether NLS is requested" >&5 +echo $ECHO_N "checking whether NLS is requested... $ECHO_C" >&6 + # Check whether --enable-nls or --disable-nls was given. +if test "${enable_nls+set}" = set; then + enableval="$enable_nls" + USE_NLS=$enableval +else + USE_NLS=yes +fi; + echo "$as_me:$LINENO: result: $USE_NLS" >&5 +echo "${ECHO_T}$USE_NLS" >&6 + + + + + BUILD_INCLUDED_LIBINTL=no + USE_INCLUDED_LIBINTL=no + + LIBINTL= + LTLIBINTL= + POSUB= + + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + + echo "$as_me:$LINENO: checking whether included gettext is requested" >&5 +echo $ECHO_N "checking whether included gettext is requested... $ECHO_C" >&6 + +# Check whether --with-included-gettext or --without-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; + echo "$as_me:$LINENO: result: $nls_cv_force_use_gnu_gettext" >&5 +echo "${ECHO_T}$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 + + + + + + + echo "$as_me:$LINENO: checking for GNU gettext in libc" >&5 +echo $ECHO_N "checking for GNU gettext in libc... $ECHO_C" >&6 +if test "${gt_cv_func_gnugettext1_libc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings; +int +main () +{ +bindtextdomain ("", ""); +return (int) gettext ("") + _nl_msg_cat_cntr + *_nl_domain_bindings + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + gt_cv_func_gnugettext1_libc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +gt_cv_func_gnugettext1_libc=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $gt_cv_func_gnugettext1_libc" >&5 +echo "${ECHO_T}$gt_cv_func_gnugettext1_libc" >&6 + + if test "$gt_cv_func_gnugettext1_libc" != "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 or --without-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/lib" + fi + fi + +fi; + LIBINTL= + LTLIBINTL= + INCINTL= + 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= + if test $use_additional = yes; then + if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then + found_dir="$additional_libdir" + found_so="$additional_libdir/lib$name.$shlibext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + else + if test -f "$additional_libdir/lib$name.$libext"; then + found_dir="$additional_libdir" + found_a="$additional_libdir/lib$name.$libext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + 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 "$shlibext" && test -f "$dir/lib$name.$shlibext"; then + found_dir="$dir" + found_so="$dir/lib$name.$shlibext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + else + if test -f "$dir/lib$name.$libext"; then + found_dir="$dir" + found_a="$dir/lib$name.$libext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + 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/lib"; 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 "$hardcode_direct" = yes; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + if test -n "$hardcode_libdir_flag_spec" && test "$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 "$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 + */lib | */lib/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` + 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*) 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/lib"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/lib"; then + if test -n "$GCC"; then + case $host_os in + linux*) 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 "$hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$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=\"$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 + + echo "$as_me:$LINENO: checking for GNU gettext in libintl" >&5 +echo $ECHO_N "checking for GNU gettext in libintl... $ECHO_C" >&6 +if test "${gt_cv_func_gnugettext1_libintl+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (); +int +main () +{ +bindtextdomain ("", ""); +return (int) gettext ("") + _nl_msg_cat_cntr + *_nl_expand_alias (0) + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + gt_cv_func_gnugettext1_libintl=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +gt_cv_func_gnugettext1_libintl=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$gt_cv_func_gnugettext1_libintl" != yes && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (); +int +main () +{ +bindtextdomain ("", ""); +return (int) gettext ("") + _nl_msg_cat_cntr + *_nl_expand_alias (0) + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + gt_cv_func_gnugettext1_libintl=yes + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS" +fi +echo "$as_me:$LINENO: result: $gt_cv_func_gnugettext1_libintl" >&5 +echo "${ECHO_T}$gt_cv_func_gnugettext1_libintl" >&6 + fi + + if test "$gt_cv_func_gnugettext1_libc" = "yes" \ + || { test "$gt_cv_func_gnugettext1_libintl" = "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" + LTLIBINTL="\${top_builddir}/intl/libintl.a $LTLIBICONV" + LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + CATOBJEXT=.gmo + fi + + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define ENABLE_NLS 1 +_ACEOF + + else + USE_NLS=no + fi + fi + + echo "$as_me:$LINENO: checking whether to use NLS" >&5 +echo $ECHO_N "checking whether to use NLS... $ECHO_C" >&6 + echo "$as_me:$LINENO: result: $USE_NLS" >&5 +echo "${ECHO_T}$USE_NLS" >&6 + if test "$USE_NLS" = "yes"; then + echo "$as_me:$LINENO: checking where the gettext function comes from" >&5 +echo $ECHO_N "checking where the gettext function comes from... $ECHO_C" >&6 + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if test "$gt_cv_func_gnugettext1_libintl" = "yes"; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + echo "$as_me:$LINENO: result: $gt_source" >&5 +echo "${ECHO_T}$gt_source" >&6 + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if test "$gt_cv_func_gnugettext1_libintl" = "yes"; then + echo "$as_me:$LINENO: checking how to link with libintl" >&5 +echo $ECHO_N "checking how to link with libintl... $ECHO_C" >&6 + echo "$as_me:$LINENO: result: $LIBINTL" >&5 +echo "${ECHO_T}$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 + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GETTEXT 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DCGETTEXT 1 +_ACEOF + + 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 + + + if test "$USE_INCLUDED_LIBINTL" = yes; then + INTLOBJS="\$(GETTOBJS)" + fi + + + INTL_LIBTOOL_SUFFIX_PREFIX= + + + + INTLLIBS="$LIBINTL" + + + + + + + +BOILERPLATE=boilerplate.mk + +if (sh -c "make --version" 2>/dev/null | grep GNU 2>&1 >/dev/null); then + if sh -c "vncmkdepend" >/dev/null 2>&1; then + BOILERPLATE="$BOILERPLATE:depend.mk" + fi +fi + + ac_config_files="$ac_config_files Makefile:Makefile.in:$BOILERPLATE intl/Makefile po/Makefile.in rdr/Makefile:rdr/Makefile.in:$BOILERPLATE network/Makefile:network/Makefile.in:$BOILERPLATE Xregion/Makefile:Xregion/Makefile.in:$BOILERPLATE rfb/Makefile:rfb/Makefile.in:$BOILERPLATE tx/Makefile:tx/Makefile.in:$BOILERPLATE x0vncserver/Makefile:x0vncserver/Makefile.in:$BOILERPLATE vncviewer_unix/Makefile:vncviewer_unix/Makefile.in:$BOILERPLATE vncconfig_unix/Makefile:vncconfig_unix/Makefile.in:$BOILERPLATE vncpasswd/Makefile:vncpasswd/Makefile.in:$BOILERPLATE" +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, don't put newlines in cache variables' values. +# 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. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *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 \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + 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}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ 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[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then we branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +cat >confdef2opt.sed <<\_ACEOF +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g +t quote +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g +t quote +d +: quote +s,[ `~#$^&*(){}\\|;'"<>?],\\&,g +s,\[,\\&,g +s,\],\\&,g +s,\$,$$,g +p +_ACEOF +# We use echo to avoid assuming a particular line-breaking character. +# The extra dot is to prevent the shell from consuming trailing +# line-breaks from the sub-command output. A line-break within +# single-quotes doesn't work because, if this script is created in a +# platform that uses two characters for line-breaks (e.g., DOS), tr +# would break. +ac_LF_and_DOT=`echo; echo .` +DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` +rm -f confdef2opt.sed + + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $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} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# 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+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; 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 + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# 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 + +# 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 + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + 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 + + ;; + 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 + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # 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 sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# 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'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -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 + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Configuration commands: +$config_commands + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +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=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + 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 +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS section. +# + +# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + + +_ACEOF + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile:Makefile.in:$BOILERPLATE" ;; + "intl/Makefile" ) CONFIG_FILES="$CONFIG_FILES intl/Makefile" ;; + "po/Makefile.in" ) CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; + "rdr/Makefile" ) CONFIG_FILES="$CONFIG_FILES rdr/Makefile:rdr/Makefile.in:$BOILERPLATE" ;; + "network/Makefile" ) CONFIG_FILES="$CONFIG_FILES network/Makefile:network/Makefile.in:$BOILERPLATE" ;; + "Xregion/Makefile" ) CONFIG_FILES="$CONFIG_FILES Xregion/Makefile:Xregion/Makefile.in:$BOILERPLATE" ;; + "rfb/Makefile" ) CONFIG_FILES="$CONFIG_FILES rfb/Makefile:rfb/Makefile.in:$BOILERPLATE" ;; + "tx/Makefile" ) CONFIG_FILES="$CONFIG_FILES tx/Makefile:tx/Makefile.in:$BOILERPLATE" ;; + "x0vncserver/Makefile" ) CONFIG_FILES="$CONFIG_FILES x0vncserver/Makefile:x0vncserver/Makefile.in:$BOILERPLATE" ;; + "vncviewer_unix/Makefile" ) CONFIG_FILES="$CONFIG_FILES vncviewer_unix/Makefile:vncviewer_unix/Makefile.in:$BOILERPLATE" ;; + "vncconfig_unix/Makefile" ) CONFIG_FILES="$CONFIG_FILES vncconfig_unix/Makefile:vncconfig_unix/Makefile.in:$BOILERPLATE" ;; + "vncpasswd/Makefile" ) CONFIG_FILES="$CONFIG_FILES vncpasswd/Makefile:vncpasswd/Makefile.in:$BOILERPLATE" ;; + "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + 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_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 to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@PACKAGE@,$PACKAGE,;t t +s,@VERSION@,$VERSION,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@CXX@,$CXX,;t t +s,@CXXFLAGS@,$CXXFLAGS,;t t +s,@ac_ct_CXX@,$ac_ct_CXX,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@MITSHM_DEFINE@,$MITSHM_DEFINE,;t t +s,@CXXCPP@,$CXXCPP,;t t +s,@X_CFLAGS@,$X_CFLAGS,;t t +s,@X_PRE_LIBS@,$X_PRE_LIBS,;t t +s,@X_LIBS@,$X_LIBS,;t t +s,@X_EXTRA_LIBS@,$X_EXTRA_LIBS,;t t +s,@ZLIB_DIR@,$ZLIB_DIR,;t t +s,@ZLIB_INCLUDE@,$ZLIB_INCLUDE,;t t +s,@ZLIB_LIB@,$ZLIB_LIB,;t t +s,@JPEG_DIR@,$JPEG_DIR,;t t +s,@JPEG_INCLUDE@,$JPEG_INCLUDE,;t t +s,@JPEG_LIB@,$JPEG_LIB,;t t +s,@VNCCONFIG_DIR@,$VNCCONFIG_DIR,;t t +s,@XTEST_DEFINE@,$XTEST_DEFINE,;t t +s,@XTEST_LIB@,$XTEST_LIB,;t t +s,@READDISPLAY_DEFINE@,$READDISPLAY_DEFINE,;t t +s,@VSNPRINTF_DEFINE@,$VSNPRINTF_DEFINE,;t t +s,@STRCASECMP_DEFINE@,$STRCASECMP_DEFINE,;t t +s,@STRNCASECMP_DEFINE@,$STRNCASECMP_DEFINE,;t t +s,@INET_LIB@,$INET_LIB,;t t +s,@SOCKLEN_T_DEFINE@,$SOCKLEN_T_DEFINE,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@MKINSTALLDIRS@,$MKINSTALLDIRS,;t t +s,@USE_NLS@,$USE_NLS,;t t +s,@MSGFMT@,$MSGFMT,;t t +s,@GMSGFMT@,$GMSGFMT,;t t +s,@XGETTEXT@,$XGETTEXT,;t t +s,@MSGMERGE@,$MSGMERGE,;t t +s,@build@,$build,;t t +s,@build_cpu@,$build_cpu,;t t +s,@build_vendor@,$build_vendor,;t t +s,@build_os@,$build_os,;t t +s,@host@,$host,;t t +s,@host_cpu@,$host_cpu,;t t +s,@host_vendor@,$host_vendor,;t t +s,@host_os@,$host_os,;t t +s,@EGREP@,$EGREP,;t t +s,@ALLOCA@,$ALLOCA,;t t +s,@GLIBC21@,$GLIBC21,;t t +s,@HAVE_POSIX_PRINTF@,$HAVE_POSIX_PRINTF,;t t +s,@HAVE_ASPRINTF@,$HAVE_ASPRINTF,;t t +s,@HAVE_SNPRINTF@,$HAVE_SNPRINTF,;t t +s,@HAVE_WPRINTF@,$HAVE_WPRINTF,;t t +s,@LIBICONV@,$LIBICONV,;t t +s,@LTLIBICONV@,$LTLIBICONV,;t t +s,@INTLBISON@,$INTLBISON,;t t +s,@BUILD_INCLUDED_LIBINTL@,$BUILD_INCLUDED_LIBINTL,;t t +s,@USE_INCLUDED_LIBINTL@,$USE_INCLUDED_LIBINTL,;t t +s,@CATOBJEXT@,$CATOBJEXT,;t t +s,@DATADIRNAME@,$DATADIRNAME,;t t +s,@INSTOBJEXT@,$INSTOBJEXT,;t t +s,@GENCAT@,$GENCAT,;t t +s,@INTLOBJS@,$INTLOBJS,;t t +s,@INTL_LIBTOOL_SUFFIX_PREFIX@,$INTL_LIBTOOL_SUFFIX_PREFIX,;t t +s,@INTLLIBS@,$INTLLIBS,;t t +s,@LIBINTL@,$LIBINTL,;t t +s,@LTLIBINTL@,$LTLIBINTL,;t t +s,@POSUB@,$POSUB,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # 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. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;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,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 +echo "$as_me: executing $ac_dest commands" >&6;} + case $ac_dest in + default-1 ) + 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 + 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" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assigment from automake. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + 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 ;; + esac +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# 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 || { (exit 1); exit 1; } +fi + diff --git a/unix/configure.in b/unix/configure.in new file mode 100644 index 00000000..9b58f275 --- /dev/null +++ b/unix/configure.in @@ -0,0 +1,198 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(vncviewer_unix/vncviewer.cxx) + +PACKAGE=tightvnc +VERSION=1.5.0 +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE") +AC_DEFINE_UNQUOTED(VERSION, "$VERSION") +AC_SUBST(PACKAGE) +AC_SUBST(VERSION) + +dnl dirty hack to prevent use of -g in CFLAGS and CXXFLAGS +ac_cv_prog_cc_g=no +ac_cv_prog_cxx_g=no + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CXX +AC_PROG_RANLIB +AC_PROG_MAKE_SET +AC_LANG_CPLUSPLUS + +case "`(uname -sr) 2>/dev/null`" in +"SunOS 5"*) + SOLARIS=yes + USE_MITSHM=yes + USE_SUN_OVL=yes + ;; +"Linux"*) + LINUX=yes + USE_MITSHM=yes + ;; +"IRIX 6"*) + X_LIBS="-L/usr/lib32" + USE_MITSHM=yes + USE_READDISPLAY=yes + ;; +"LynxOS 2"*) + SJLJ_EXCEPTIONS=yes + ;; +esac + +dnl FIXME: Check for MIT-SHM properly, add a corresponding --with option. +if test "$USE_MITSHM" = yes; then + MITSHM_DEFINE="-DHAVE_MITSHM" +fi +AC_SUBST(MITSHM_DEFINE) + +if test "$GCC" = yes; then + CFLAGS="$CFLAGS -Wall" + if test "$SOLARIS" = yes; then + CFLAGS="$CFLAGS -Wno-unknown-pragmas -Wno-implicit-int" + fi +fi +if test "$GXX" = yes; then + CXXFLAGS="$CXXFLAGS -Wall" + if test "$SOLARIS" = yes; then + CXXFLAGS="$CXXFLAGS -Wno-unknown-pragmas -fpermissive" + fi + if test "$SJLJ_EXCEPTIONS" = yes; then + CXXFLAGS="$CXXFLAGS -fsjlj-exceptions" + fi +fi + +AC_PATH_XTRA + +AC_ARG_WITH(installed-zlib, +[ --with-installed-zlib use the version of zlib which is installed on the + system instead of the one distributed with VNC]) + +if test "$with_installed_zlib" = yes; then + echo "using installed zlib" + ZLIB_LIB=-lz +else + ZLIB_DIR=zlib + ZLIB_INCLUDE='-I$(top_srcdir)/zlib' + ZLIB_LIB='$(top_srcdir)/zlib/libz.a' + echo "configuring zlib..." + (cd zlib; ./configure) + echo "...done configuring zlib" +fi + +AC_SUBST(ZLIB_DIR) +AC_SUBST(ZLIB_INCLUDE) +AC_SUBST(ZLIB_LIB) + +AC_ARG_WITH(installed-jpeg, +[ --with-installed-jpeg use the version of jpeg which is installed on the + system instead of the one distributed with VNC]) + +if test "$with_installed_jpeg" = yes; then + echo "using installed jpeg" + JPEG_LIB=-ljpeg +else + JPEG_DIR=jpeg/build + JPEG_INCLUDE='-I$(top_srcdir)/jpeg' + JPEG_LIB='$(top_srcdir)/jpeg/build/libjpeg.a' + echo "configuring jpeg..." + (mkdir jpeg/build; cd jpeg/build; ../configure) + echo "...done configuring jpeg" +fi + +AC_SUBST(JPEG_DIR) +AC_SUBST(JPEG_INCLUDE) +AC_SUBST(JPEG_LIB) + +AC_ARG_ENABLE(vncconfig, +[ --enable-vncconfig build the vncconfig utility (assumed by default), + use --disable-vncconfig to skip building vncconfig]) +if test "$enable_vncconfig" = no; then + echo "vncconfig utility will not be built" + VNCCONFIG_DIR= +else + VNCCONFIG_DIR='vncconfig_unix' +fi +AC_SUBST(VNCCONFIG_DIR) + +dnl Check for the XTest X11 extension library. +AC_CHECK_LIB(Xtst,XTestGrabControl,USE_XTEST=yes,USE_XTEST=, +["$X_LIBS" -lXext -lX11]) +if test "$USE_XTEST" = yes; then + XTEST_DEFINE='-DHAVE_XTEST' + XTEST_LIB=-lXtst +else + echo Warning: No XTest extension, building x0vncserver view-only + XTEST_DEFINE= + XTEST_LIB= +fi +AC_SUBST(XTEST_DEFINE) +AC_SUBST(XTEST_LIB) + +dnl Support for READDISPLAY (Irix) and SUN_OVL (Solaris) extensions +dnl FIXME: Implement corresponding --with options. +if test "$USE_READDISPLAY" = yes; then + READDISPLAY_DEFINE='-DHAVE_READDISPLAY' +elif test "$USE_SUN_OVL" = yes; then + READDISPLAY_DEFINE='-DHAVE_SUN_OVL' +else + READDISPLAY_DEFINE= +fi +AC_SUBST(READDISPLAY_DEFINE) + +AC_CHECK_FUNC(vsnprintf,VSNPRINTF_DEFINE='-DHAVE_VSNPRINTF',VSNPRINTF_DEFINE=) +AC_SUBST(VSNPRINTF_DEFINE) + +AC_CHECK_FUNC(strcasecmp,STRCASECMP_DEFINE='-DHAVE_STRCASECMP', + STRCASECMP_DEFINE=) +AC_SUBST(STRCASECMP_DEFINE) + +AC_CHECK_FUNC(strncasecmp,STRNCASECMP_DEFINE='-DHAVE_STRNCASECMP', + STRNCASECMP_DEFINE=) +AC_SUBST(STRNCASECMP_DEFINE) + +dnl Under Lynx/OS 2.3, we have to link with -lbsd to resolve +dnl gethostbyname, inet_addr, htons etc. Check if it's necessary. +dnl NOTE: Did not want to use AC_SEARCH_LIBS which would add +dnl -lbsd to LIBS. We set INET_LIB instead. +AC_LANG_SAVE +AC_LANG_C +AC_CHECK_FUNC(gethostbyname,INET_LIB_REQ=,INET_LIB_REQ=yes) +if test "$INET_LIB_REQ" = yes; then + AC_CHECK_LIB(bsd,gethostbyname,INET_LIB=-lbsd,INET_LIB=) +fi +AC_LANG_RESTORE +AC_SUBST(INET_LIB) + +AC_MSG_CHECKING(for socklen_t) +AC_TRY_COMPILE( +[#include + #include ], +[socklen_t x; +accept(0, 0, &x);], +AC_MSG_RESULT(yes) +SOCKLEN_T_DEFINE='-DVNC_SOCKLEN_T=socklen_t', +AC_MSG_RESULT(using int) +SOCKLEN_T_DEFINE='-DVNC_SOCKLEN_T=int') +AC_SUBST(SOCKLEN_T_DEFINE) + +AM_GNU_GETTEXT + +BOILERPLATE=boilerplate.mk + +if (sh -c "make --version" 2>/dev/null | grep GNU 2>&1 >/dev/null); then + if sh -c "vncmkdepend" >/dev/null 2>&1; then + BOILERPLATE="$BOILERPLATE:depend.mk" + fi +fi + +AC_OUTPUT(Makefile:Makefile.in:$BOILERPLATE intl/Makefile po/Makefile.in \ + rdr/Makefile:rdr/Makefile.in:$BOILERPLATE \ + network/Makefile:network/Makefile.in:$BOILERPLATE \ + Xregion/Makefile:Xregion/Makefile.in:$BOILERPLATE \ + rfb/Makefile:rfb/Makefile.in:$BOILERPLATE \ + tx/Makefile:tx/Makefile.in:$BOILERPLATE \ + x0vncserver/Makefile:x0vncserver/Makefile.in:$BOILERPLATE \ + vncviewer_unix/Makefile:vncviewer_unix/Makefile.in:$BOILERPLATE \ + vncconfig_unix/Makefile:vncconfig_unix/Makefile.in:$BOILERPLATE \ + vncpasswd/Makefile:vncpasswd/Makefile.in:$BOILERPLATE \ +) diff --git a/unix/depend.mk b/unix/depend.mk new file mode 100644 index 00000000..51d4cd63 --- /dev/null +++ b/unix/depend.mk @@ -0,0 +1,76 @@ +# +# C / C++ header dependency stuff +# +# Needs GNU make and vncmkdepend, a hacked version of makedepend + +.SUFFIXES: .d + +CMAKEDEPEND = vncmkdepend +CXXMAKEDEPEND = vncmkdepend + +# +# The recommended method of doing dependency analysis in the GNU make manual +# turns out to be painfully slow. This method is similar but it's +# substantially faster and retains the desirable property that the user doesn't +# need to manually invoke a "make depend" step. +# +# As with the method described in the manual, we generate a separate dependency +# (.d) file for each source file. The .d file records the header files that +# each C or C++ source file includes. Any source file recorded in SRCS or +# CXXSRCS will cause us to try and include the corresponding .d file and GNU +# make then treats each .d file as a target to be remade. +# +# Unlike the manual's method, the rule we provide for making the .d file is +# actually a fake. All it does is record in a temporary file that the .d file +# needs to be remade. But as well as all the .d files, we also try to include +# a file called "depend.phony". This file never exists, but it causes GNU make +# to try and make the target "depend.phony". The rule for depend.phony then +# looks at the temporary files generated by the .d rules and then invokes the +# "omkdepend" program on all of the source files in one go. +# + +# +# We use simple assignment here to remove any of the depend.tmp files +# at the time make parses this bit. +# + +dummyvariable := $(shell $(RM) cdepend.tmp cxxdepend.tmp) + +# +# Now the "fake" rules for generating .d files. +# + +%.d: %.c + @echo "$<" >> cdepend.tmp + +%.d: %.cxx + @echo "$<" >> cxxdepend.tmp + +# +# The depend.phony rule which actually runs omkdepend. +# + +depend.phony: + @if [ -f cdepend.tmp ]; then \ + echo $(CMAKEDEPEND) $(ALL_CPPFLAGS) `cat cdepend.tmp`; \ + $(CMAKEDEPEND) $(ALL_CPPFLAGS) `cat cdepend.tmp`; \ + rm -f cdepend.tmp; \ + fi; \ + if [ -f cxxdepend.tmp ]; then \ + echo $(CXXMAKEDEPEND) $(ALL_CPPFLAGS) `cat cxxdepend.tmp`; \ + $(CXXMAKEDEPEND) $(ALL_CPPFLAGS) `cat cxxdepend.tmp`; \ + rm -f cxxdepend.tmp; \ + fi + +# +# Now include the .d files and the "depend.phony" file which never exists. +# For some reason GNU make evaluates the targets in reverse order, so we need +# to include depend.phony first. The "-" tells make not to complain that it +# can't find the file. +# + +-include depend.phony + +ifdef SRCS +-include $(patsubst %.c,%.d,$(patsubst %.cxx,%.d,$(SRCS))) +endif diff --git a/unix/hpux.patch b/unix/hpux.patch new file mode 100644 index 00000000..389c6751 --- /dev/null +++ b/unix/hpux.patch @@ -0,0 +1,255 @@ +*** xc.orig/config/cf/X11.tmpl Tue Jan 15 22:55:26 2002 +--- xc/config/cf/X11.tmpl Sun Sep 7 19:52:01 2003 +*************** +*** 3120,3126 **** + $(RM) index.raw file.nPS file.PS file.txt + #endif + +! #ifndef MakeSimpleDoc(file,srcs) + #define MakeSimpleDoc(file,srcs) MakeDepSimpleDoc(file,srcs,srcs) + #endif + +--- 3120,3126 ---- + $(RM) index.raw file.nPS file.PS file.txt + #endif + +! #ifndef MakeSimpleDoc + #define MakeSimpleDoc(file,srcs) MakeDepSimpleDoc(file,srcs,srcs) + #endif + +*** xc.orig/config/cf/hp.cf Wed Jan 17 16:22:31 2001 +--- xc/config/cf/hp.cf Mon Sep 8 19:54:52 2003 +*************** +*** 131,137 **** + #endif + #define HPFastScrolling YES + #ifndef BuildServer +! # define BuildServer __hp9000s700 + #endif + #if OSMajorVersion < 10 + #define NeedBerklib (BuildServer|BuildFontServer) +--- 131,137 ---- + #endif + #define HPFastScrolling YES + #ifndef BuildServer +! # define BuildServer YES + #endif + #if OSMajorVersion < 10 + #define NeedBerklib (BuildServer|BuildFontServer) +*************** +*** 139,145 **** + #define XawI18nDefines -DHAS_WCHAR_H -DHAS_ISW_FUNCS + + #if OSMajorVersion < 6 || (OSMajorVersion == 6 && OSMinorVersion < 2) +! # define ConnectionFlags -DTCPCONN /* no unix sockets */ + #endif + + #if OSMajorVersion > 8 +--- 139,145 ---- + #define XawI18nDefines -DHAS_WCHAR_H -DHAS_ISW_FUNCS + + #if OSMajorVersion < 6 || (OSMajorVersion == 6 && OSMinorVersion < 2) +! /*# define ConnectionFlags -DTCPCONN*/ /* no unix sockets */ + #endif + + #if OSMajorVersion > 8 +*** xc/config/cf/site.def.orig Tue Sep 9 17:42:56 2003 +--- xc/config/cf/site.def Tue Sep 9 17:43:07 2003 +*************** +*** 84,90 **** + #ifdef AfterVendorCF + + #ifndef ProjectRoot +! #define ProjectRoot /usr/X11R6 + #endif + + /* +--- 84,90 ---- + #ifdef AfterVendorCF + + #ifndef ProjectRoot +! /*#define ProjectRoot /usr/X11R6*/ + #endif + + /* +*** xc.orig/config/imake/imake.c Fri Dec 14 19:53:18 2001 +--- xc/config/imake/imake.c Mon Sep 8 19:35:33 2003 +*************** +*** 288,293 **** +--- 288,294 ---- + #define TRUE 1 + #define FALSE 0 + ++ #define FIXUP_CPP_WHITESPACE + #ifdef FIXUP_CPP_WHITESPACE + int InRule = FALSE; + # ifdef INLINE_SYNTAX +*************** +*** 389,394 **** +--- 390,401 ---- + FILE *tmpfd = NULL; + char makeMacro[ BUFSIZ ]; + char makefileMacro[ BUFSIZ ]; ++ ++ #ifdef FIXUP_CPP_WHITESPACE ++ fprintf(stderr,"\nFIXUP_CPP_WHITESPACE is defined!!\n\n"); ++ #else ++ #error "FIXUP_CPP_WHITESPACE is not defined" ++ #endif + + program = argv[0]; + init(); +*** xc.orig/config/imake/imakemdep.h Fri Dec 14 19:53:19 2001 +--- xc/config/imake/imakemdep.h Tue Sep 9 16:38:18 2003 +*************** +*** 48,54 **** + #ifdef hp9000s800 + #define imake_ccflags "-DSYSV" + #else +! #define imake_ccflags "-Wc,-Nd4000,-Ns3000 -DSYSV" + #endif + #endif + +--- 48,54 ---- + #ifdef hp9000s800 + #define imake_ccflags "-DSYSV" + #else +! #define imake_ccflags "-DSYSV" + #endif + #endif + +*************** +*** 211,217 **** + * all colons). One way to tell if you need this is to see whether or not + * your Makefiles have no tabs in them and lots of @@ strings. + */ +! #if defined(sun) || defined(SYSV) || defined(SVR4) || defined(hcx) || defined(WIN32) || defined(sco) || (defined(AMOEBA) && defined(CROSS_COMPILE)) || defined(__QNX__) || defined(__sgi) + #define FIXUP_CPP_WHITESPACE + #endif + #ifdef WIN32 +--- 211,217 ---- + * all colons). One way to tell if you need this is to see whether or not + * your Makefiles have no tabs in them and lots of @@ strings. + */ +! #if defined(sun) || defined(SYSV) || defined(SVR4) || defined(hcx) || defined(WIN32) || defined(sco) || (defined(AMOEBA) && defined(CROSS_COMPILE)) || defined(__QNX__) || defined(__sgi) || defined(hpux) + #define FIXUP_CPP_WHITESPACE + #endif + #ifdef WIN32 +*** xc.orig/include/Xfuncs.h Fri Dec 14 19:53:25 2001 +--- xc/include/Xfuncs.h Sun Sep 7 20:10:35 2003 +*************** +*** 42,48 **** + #else + #if defined(SYSV) + #include +! void bcopy(); + #define bzero(b,len) memset(b, 0, len) + #define bcmp(b1,b2,len) memcmp(b1, b2, len) + #elif defined(__EMX__) +--- 42,48 ---- + #else + #if defined(SYSV) + #include +! /*void bcopy();*/ + #define bzero(b,len) memset(b, 0, len) + #define bcmp(b1,b2,len) memcmp(b1, b2, len) + #elif defined(__EMX__) +*** xc.orig/include/extensions/security.h Fri Dec 14 19:53:29 2001 +--- xc/include/extensions/security.h Fri Aug 1 17:43:44 2003 +*************** +*** 110,115 **** +--- 110,116 ---- + + #include "input.h" /* for DeviceIntPtr */ + #include "property.h" /* for PropertyPtr */ ++ #include "resource.h" + + /* resource type to pass in LookupIDByType for authorizations */ + extern RESTYPE SecurityAuthorizationResType; +*** xc.orig/lib/font/Type1/fontfcn.c Fri Nov 23 19:21:31 2001 +--- xc/lib/font/Type1/fontfcn.c Sun Sep 7 19:29:27 2003 +*************** +*** 47,52 **** +--- 47,53 ---- + */ + /* $XFree86: xc/lib/font/Type1/fontfcn.c,v 1.11 2001/11/23 19:21:31 dawes Exp $ */ + ++ #include + #ifndef FONTMODULE + #include + #include +*** xc.orig/lib/font/Type1/objects.h Mon Aug 27 20:49:52 2001 +--- xc/lib/font/Type1/objects.h Sun Sep 7 19:29:37 2003 +*************** +*** 50,56 **** + #include + #include + #ifndef FONTMODULE +! #include + #endif + /*SHARED*/ + +--- 50,56 ---- + #include + #include + #ifndef FONTMODULE +! /*#include */ + #endif + /*SHARED*/ + +*** xc.orig/lib/xtrans/Xtransutil.c Tue Sep 9 17:40:14 2003 +--- xc/lib/xtrans/Xtransutil.c Tue Sep 9 17:40:20 2003 +*************** +*** 503,514 **** + if (updateOwner && !updatedOwner) { + PRMSG(1, "mkdir: Owner of %s should be set to root\n", + path, 0, 0); +- sleep(5); + } + if (updateMode && !updatedMode) { + PRMSG(1, "mkdir: Mode of %s should be set to %04o\n", + path, mode, 0); +- sleep(5); + } + return 0; + } +--- 503,512 ---- +*** xc.orig/programs/Xserver/vnc/Xvnc/xvnc.cc 12 Aug 2003 11:00:14 -0000 +--- xc/programs/Xserver/vnc/Xvnc/xvnc.cc 9 Sep 2003 16:15:53 -0000 +*************** +*** 1221,1223 **** +--- 1221,1229 ---- + miRegisterPointerDevice(screenInfo.screens[0], p); + (void)mieqInit ((DevicePtr)k, (DevicePtr)p); + } ++ ++ extern "C" { ++ void XTestGenerateEvent() {} ++ void XTestGetPointerPos() {} ++ void XTestJumpPointer() {} ++ } +*** xc.orig/config/cf/vnc.def 7 Jul 2003 09:51:22 +--- xc/config/cf/vnc.def 9 Sep 2003 15:54:23 +*************** +*** 9,14 **** +--- 9,20 ---- + #define XnestServer NO + #define XprtServer NO + ++ #define BuildXKB NO ++ #define HasCplusplus YES ++ #define CplusplusCmd /opt/aCC/bin/aCC ++ #define CplusplusOptions -AA +W749 +W740 ++ #define ProjectRoot /usr ++ + #ifdef SunArchitecture + #define ProjectRoot /usr/openwin + #define HasGcc2 YES +*************** +*** 29,32 **** +--- 34,38 ---- + + #define ServerTarget(server,subdirs,objects,libs,syslibs) @@\ + CCLINK = $(CXXENVSETUP) $(CXX) @@\ ++ CCOPTIONS = -AA @@\ + ServerTargetWithFlags(server,subdirs,objects,libs,syslibs,$(_NOOP_)) diff --git a/unix/install-sh b/unix/install-sh new file mode 100755 index 00000000..dd97db7a --- /dev/null +++ b/unix/install-sh @@ -0,0 +1,322 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2004-09-10.20 + +# 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. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +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: +-c (ignored) +-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. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit 0;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit 0;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; 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 + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + 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 "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # 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 -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # 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 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $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 "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 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. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/unix/intl/ChangeLog b/unix/intl/ChangeLog new file mode 100644 index 00000000..75129192 --- /dev/null +++ b/unix/intl/ChangeLog @@ -0,0 +1,4 @@ +2004-01-29 GNU + + * Version 0.14.1 released. + diff --git a/unix/intl/Makefile.in b/unix/intl/Makefile.in new file mode 100644 index 00000000..c3468f92 --- /dev/null +++ b/unix/intl/Makefile.in @@ -0,0 +1,493 @@ +# Makefile for directory with message catalog handling library of GNU gettext +# Copyright (C) 1995-1998, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = .. +VPATH = $(srcdir) + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +transform = @program_transform_name@ +libdir = @libdir@ +includedir = @includedir@ +datadir = @datadir@ +localedir = $(datadir)/locale +gettextsrcdir = $(datadir)/gettext/intl +aliaspath = $(localedir) +subdir = intl + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +mkinstalldirs = $(SHELL) $(MKINSTALLDIRS) + +l = @INTL_LIBTOOL_SUFFIX_PREFIX@ + +AR = ar +CC = @CC@ +LIBTOOL = @LIBTOOL@ +RANLIB = @RANLIB@ +YACC = @INTLBISON@ -y -d +YFLAGS = --name-prefix=__gettext + +DEFS = -DLOCALEDIR=\"$(localedir)\" -DLOCALE_ALIAS_PATH=\"$(aliaspath)\" \ +-DLIBDIR=\"$(libdir)\" -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@ +LDFLAGS = @LDFLAGS@ +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 \ + relocatable.h \ + 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 \ + 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 \ + relocatable.c \ + localename.c \ + log.c \ + printf.c \ + osdep.c \ + os2compat.c \ + intl-compat.c +OBJECTS = \ + bindtextdom.$lo \ + dcgettext.$lo \ + dgettext.$lo \ + gettext.$lo \ + finddomain.$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 \ + relocatable.$lo \ + localename.$lo \ + log.$lo \ + printf.$lo \ + osdep.$lo \ + intl-compat.$lo +DISTFILES.common = Makefile.in \ +config.charset locale.alias ref-add.sin ref-del.sin $(HEADERS) $(SOURCES) +DISTFILES.generated = plural.c +DISTFILES.normal = VERSION +DISTFILES.gettext = COPYING.LIB-2.0 COPYING.LIB-2.1 libintl.glibc \ +libgnuintl.h_vms Makefile.vms \ +libgnuintl.h.msvc-static libgnuintl.h.msvc-shared README.woe32 Makefile.msvc +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 + +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) + $(LIBTOOL) --mode=link \ + $(CC) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ \ + $(OBJECTS) @LTLIBICONV@ $(LIBS) -lc \ + -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=7 +LTV_REVISION=0 +LTV_AGE=4 + +.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 +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 +relocatable.lo: $(srcdir)/relocatable.c + $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/relocatable.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 +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 + +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 '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 > libgnuintl.h + +libintl.h: libgnuintl.h + cp libgnuintl.h 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 \ + $(mkinstalldirs) $(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; then \ + $(mkinstalldirs) $(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 || $(mkinstalldirs) $(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; \ + $(mkinstalldirs) $(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 \ + $(mkinstalldirs) $(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 + +installdirs: + if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \ + && test '@USE_INCLUDED_LIBINTL@' = yes; then \ + $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \ + else \ + : ; \ + fi + if test "$(PACKAGE)" = "gettext-tools" \ + && test '@USE_INCLUDED_LIBINTL@' = no; then \ + $(mkinstalldirs) $(DESTDIR)$(libdir); \ + else \ + : ; \ + fi + if test '@USE_INCLUDED_LIBINTL@' = yes; then \ + test @GLIBC21@ != no || $(mkinstalldirs) $(DESTDIR)$(libdir); \ + $(mkinstalldirs) $(DESTDIR)$(localedir); \ + else \ + : ; \ + fi + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkinstalldirs) $(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; 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): 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 +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 +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 + +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) + here=`pwd`; cd $(srcdir) && etags -o $$here/TAGS $(HEADERS) $(SOURCES) + +ctags: CTAGS + +CTAGS: $(HEADERS) $(SOURCES) + here=`pwd`; cd $(srcdir) && ctags -o $$here/CTAGS $(HEADERS) $(SOURCES) + +id: ID + +ID: $(HEADERS) $(SOURCES) + here=`pwd`; cd $(srcdir) && mkid -f$$here/ID $(HEADERS) $(SOURCES) + + +mostlyclean: + rm -f *.a *.la *.o *.obj *.lo core core.* + rm -f libgnuintl.h libintl.h charset.alias ref-add.sed ref-del.sed + rm -f -r .libs _libs + +clean: mostlyclean + +distclean: clean + rm -f Makefile ID TAGS + if test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; then \ + rm -f ChangeLog.inst $(DISTFILES.normal); \ + else \ + : ; \ + fi + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + + +# GNU gettext needs not contain the file `VERSION' but contains some +# other files which should not be distributed in other packages. +distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: Makefile + if test "$(PACKAGE)" = "gettext-tools"; then \ + : ; \ + else \ + if test "$(PACKAGE)" = "gettext-runtime"; then \ + additional="$(DISTFILES.gettext)"; \ + else \ + additional="$(DISTFILES.normal)"; \ + fi; \ + $(MAKE) $(DISTFILES.common) $(DISTFILES.generated) $$additional; \ + for file in ChangeLog $(DISTFILES.common) $(DISTFILES.generated) $$additional; do \ + if test -f $$file; then dir=.; else dir=$(srcdir); fi; \ + cp -p $$dir/$$file $(distdir); \ + 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) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/unix/intl/VERSION b/unix/intl/VERSION new file mode 100644 index 00000000..b4b846ca --- /dev/null +++ b/unix/intl/VERSION @@ -0,0 +1 @@ +GNU gettext library from gettext-0.14.1 diff --git a/unix/intl/bindtextdom.c b/unix/intl/bindtextdom.c new file mode 100644 index 00000000..dcdc4008 --- /dev/null +++ b/unix/intl/bindtextdom.c @@ -0,0 +1,363 @@ +/* Implementation of the bindtextdomain(3) function + Copyright (C) 1995-1998, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#ifdef _LIBC +# include +#else +# include "libgnuintl.h" +#endif +#include "gettextP.h" + +#ifdef _LIBC +/* We have to handle multi-threaded applications. */ +# include +#else +/* Provide dummy implementation if this is outside glibc. */ +# define __libc_rwlock_define(CLASS, NAME) +# define __libc_rwlock_wrlock(NAME) +# define __libc_rwlock_unlock(NAME) +#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 + +/* 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 @@ */ + +/* Contains the default location of the message catalogs. */ +extern const char _nl_default_dirname[]; +#ifdef _LIBC +extern const char _nl_default_dirname_internal[] attribute_hidden; +#else +# define INTUSE(name) name +#endif + +/* List with bindings of specific domains. */ +extern struct binding *_nl_domain_bindings; + +/* Lock variable to protect the global data in the gettext implementation. */ +__libc_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; + } + + __libc_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, INTUSE(_nl_default_dirname)) == 0) + result = (char *) INTUSE(_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 != INTUSE(_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; + binding->codeset_cntr++; + modified = 1; + } + } + *codesetp = result; + } + } + } + else if ((dirnamep == NULL || *dirnamep == NULL) + && (codesetp == NULL || *codesetp == NULL)) + { + /* Simply return the default values. */ + if (dirnamep) + *dirnamep = INTUSE(_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 = INTUSE(_nl_default_dirname); + else + { + if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0) + dirname = INTUSE(_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 *) INTUSE(_nl_default_dirname); + + new_binding->codeset_cntr = 0; + + 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; + new_binding->codeset_cntr++; + } + *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 != INTUSE(_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; + + __libc_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/unix/intl/config.charset b/unix/intl/config.charset new file mode 100755 index 00000000..43d45fb7 --- /dev/null +++ b/unix/intl/config.charset @@ -0,0 +1,608 @@ +#! /bin/sh +# Output a system dependent table of character encoding aliases. +# +# Copyright (C) 2000-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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# 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 darwin +# ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd darwin +# ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd darwin +# ISO-8859-3 Y glibc solaris +# ISO-8859-4 Y osf solaris freebsd darwin +# ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd darwin +# ISO-8859-6 Y glibc aix hpux solaris +# ISO-8859-7 Y glibc aix hpux irix osf solaris +# ISO-8859-8 Y glibc aix hpux osf solaris +# ISO-8859-9 Y glibc aix hpux irix osf solaris +# ISO-8859-13 glibc +# ISO-8859-14 glibc +# ISO-8859-15 glibc aix osf solaris freebsd +# KOI8-R Y glibc solaris freebsd darwin +# KOI8-U Y glibc freebsd 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 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 darwin woe32 +# CP1252 aix woe32 +# CP1253 woe32 +# CP1254 woe32 +# CP1255 glibc woe32 +# CP1256 woe32 +# CP1257 woe32 +# GB2312 Y glibc aix hpux irix solaris freebsd darwin +# EUC-JP Y glibc aix hpux irix osf solaris freebsd darwin +# EUC-KR Y glibc aix hpux irix osf solaris freebsd darwin +# EUC-TW glibc aix hpux irix osf solaris +# BIG5 Y glibc aix hpux osf solaris freebsd darwin +# BIG5-HKSCS glibc solaris +# GBK glibc aix osf solaris woe32 dos +# GB18030 glibc solaris +# SHIFT_JIS Y hpux osf solaris freebsd 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 +# +# 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-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*) + # 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" + ;; + 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/unix/intl/dcgettext.c b/unix/intl/dcgettext.c new file mode 100644 index 00000000..850acdee --- /dev/null +++ b/unix/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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/unix/intl/dcigettext.c b/unix/intl/dcigettext.c new file mode 100644 index 00000000..35238e2c --- /dev/null +++ b/unix/intl/dcigettext.c @@ -0,0 +1,1219 @@ +/* Implementation of the internal dcigettext 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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 + +#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 + +#include "gettextP.h" +#include "plural-exp.h" +#ifdef _LIBC +# include +#else +# include "libgnuintl.h" +#endif +#include "hash-string.h" + +/* Thread safetyness. */ +#ifdef _LIBC +# include +#else +/* Provide dummy implementation if this is outside glibc. */ +# define __libc_lock_define_initialized(CLASS, NAME) +# define __libc_lock_lock(NAME) +# define __libc_lock_unlock(NAME) +# define __libc_rwlock_define_initialized(CLASS, NAME) +# define __libc_rwlock_rdlock(NAME) +# define __libc_rwlock_unlock(NAME) +#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 + +/* 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 +# define _nl_default_dirname libintl_nl_default_dirname +# define _nl_domain_bindings libintl_nl_domain_bindings +#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 + +/* 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 __EMX__ || defined __DJGPP__ + /* Win32, 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 + +/* This is the type used for the search tree where known translations + are stored. */ +struct known_translation_t +{ + /* Domain in which to search. */ + char *domainname; + + /* The category. */ + int category; + + /* 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]; +}; + +/* Root of the search tree with known translations. We can use this + only if the system provides the `tsearch' function family. */ +#if defined HAVE_TSEARCH || defined _LIBC +# include + +static void *root; + +# ifdef _LIBC +# define tsearch __tsearch +# endif + +/* 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) + /* 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; +} +#endif + +#ifndef INTVARDEF +# define INTVARDEF(name) +#endif +#ifndef INTUSE +# define INTUSE(name) name +#endif + +/* 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"; + +/* Value used as the default domain for gettext(3). */ +const char *_nl_current_default_domain attribute_hidden + = _nl_default_default_domain; + +/* Contains the default location of the message catalogs. */ +#if defined __EMX__ +extern const char _nl_default_dirname[]; +#else +const char _nl_default_dirname[] = LOCALEDIR; +INTVARDEF (_nl_default_dirname) +#endif + +/* List with bindings of specific domains created by bindtextdomain() + calls. */ +struct binding *_nl_domain_bindings; + +/* 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; +static const char *guess_category_value (int category, + const char *categoryname) + internal_function; +#ifdef _LIBC +# include "../locale/localeinfo.h" +# define category_to_name(category) _nl_category_names[category] +#else +static const char *category_to_name (int category) 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. */ +#ifdef _LIBC +__libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden) +#endif + +/* 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. */ +char * +DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, + int plural, unsigned long int n, int category) +{ +#ifndef HAVE_ALLOCA + struct block_list *block_list = NULL; +#endif + struct loaded_l10nfile *domain; + struct binding *binding; + const char *categoryname; + const char *categoryvalue; + char *dirname, *xdomainname; + char *single_locale; + char *retval; + size_t retlen; + int saved_errno; +#if defined HAVE_TSEARCH || defined _LIBC + struct known_translation_t *search; + struct known_translation_t **foundp = NULL; + size_t msgid_len; +#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 + + __libc_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 + +#if defined HAVE_TSEARCH || defined _LIBC + 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 = (char *) domainname; + search->category = category; + + foundp = (struct known_translation_t **) tfind (search, &root, transcmp); + 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; + + __libc_rwlock_unlock (_nl_state_lock); + return retval; + } +#endif + + /* Preserve the `errno' value. */ + saved_errno = errno; + + /* See whether this is a SUID binary or not. */ + DETERMINE_SECURE; + + /* First find matching binding. */ + 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 = (char *) INTUSE(_nl_default_dirname); + else if (IS_ABSOLUTE_PATH (binding->dirname)) + dirname = binding->dirname; + else + { + /* We have a relative path. Make it absolute now. */ + size_t dirname_len = strlen (binding->dirname) + 1; + size_t path_max; + char *ret; + + path_max = (unsigned int) PATH_MAX; + path_max += 2; /* The getcwd docs say to do this. */ + + for (;;) + { + dirname = (char *) alloca (path_max + dirname_len); + ADD_BLOCK (block_list, dirname); + + __set_errno (0); + ret = getcwd (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 (dirname, '\0'), "/"), binding->dirname); + } + + /* Now determine the symbolic name of CATEGORY and its value. */ + categoryname = category_to_name (category); + categoryvalue = guess_category_value (category, categoryname); + + domainname_len = strlen (domainname); + xdomainname = (char *) alloca (strlen (categoryname) + + domainname_len + 5); + ADD_BLOCK (block_list, xdomainname); + + stpcpy (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) + { + retval = _nl_find_msg (domain, binding, msgid1, &retlen); + + if (retval == NULL) + { + int cnt; + + for (cnt = 0; domain->successor[cnt] != NULL; ++cnt) + { + retval = _nl_find_msg (domain->successor[cnt], binding, + msgid1, &retlen); + + if (retval != NULL) + { + domain = domain->successor[cnt]; + break; + } + } + } + + if (retval != NULL) + { + /* Found the translation of MSGID1 in domain DOMAIN: + starting at RETVAL, RETLEN bytes. */ + FREE_BLOCKS (block_list); +#if defined HAVE_TSEARCH || defined _LIBC + if (foundp == NULL) + { + /* Create a new entry and add it to the search tree. */ + struct known_translation_t *newp; + + newp = (struct known_translation_t *) + malloc (offsetof (struct known_translation_t, msgid) + + msgid_len + domainname_len + 1); + if (newp != NULL) + { + newp->domainname = + mempcpy (newp->msgid, msgid1, msgid_len); + memcpy (newp->domainname, domainname, domainname_len + 1); + newp->category = category; + newp->counter = _nl_msg_cat_cntr; + newp->domain = domain; + newp->translation = retval; + newp->translation_length = retlen; + + /* Insert the entry in the search tree. */ + foundp = (struct known_translation_t **) + tsearch (newp, &root, transcmp); + 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; + } +#endif + __set_errno (saved_errno); + + /* Now deal with plural. */ + if (plural) + retval = plural_lookup (domain, n, retval, retlen); + + __libc_rwlock_unlock (_nl_state_lock); + return retval; + } + } + } + + return_untranslated: + /* Return the untranslated MSGID. */ + FREE_BLOCKS (block_list); + __libc_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); +} + + +char * +internal_function +_nl_find_msg (struct loaded_l10nfile *domain_file, + struct binding *domainbinding, const char *msgid, + size_t *lengthp) +{ + 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 + if (domain->codeset_cntr + != (domainbinding != NULL ? domainbinding->codeset_cntr : 0)) + { + /* The domain's codeset has changed through bind_textdomain_codeset() + since the message catalog was initialized or last accessed. We + have to reinitialize the converter. */ + _nl_free_domain_conv (domain); + _nl_init_domain_conv (domain_file, domain, domainbinding); + } + + if ( +# ifdef _LIBC + domain->conv != (__gconv_t) -1 +# else +# if HAVE_ICONV + domain->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 (domain->conv_tab == NULL + && ((domain->conv_tab = + (char **) calloc (nstrings + domain->n_sysdep_strings, + sizeof (char *))) + == NULL)) + /* Mark that we didn't succeed allocating a table. */ + domain->conv_tab = (char **) -1; + + if (__builtin_expect (domain->conv_tab == (char **) -1, 0)) + /* Nothing we can do, no more memory. */ + goto converted; + + if (domain->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 (domain->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) + { + __libc_lock_unlock (lock); + goto converted; + } + + inbuf = 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 (domain->conv, + (ICONV_CONST char **) &inptr, &inleft, + &outptr, &outleft) + != (size_t) (-1)) + { + outbuf = (unsigned char *) outptr; + break; + } + if (errno != E2BIG) + { + __libc_lock_unlock (lock); + goto converted; + } +# 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); + goto converted; + } + +# 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 = 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); + domain->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 domain->conv_tab[act] contains the translation of all + the plural variants. */ + result = domain->conv_tab[act] + sizeof (size_t); + resultlen = *(size_t *) domain->conv_tab[act]; + } + + converted: + /* 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. */ +static const char * +internal_function +guess_category_value (int category, const char *categoryname) +{ + const char *language; + const char *retval; + + /* The highest priority value is the `LANGUAGE' environment + variable. But we don't use the value if the currently selected + locale is the C locale. This is a GNU extension. */ + language = getenv ("LANGUAGE"); + if (language != NULL && language[0] == '\0') + language = NULL; + + /* We have to proceed with the POSIX methods of looking to `LC_ALL', + `LC_xxx', and `LANG'. On some systems this can be done by the + `setlocale' function itself. */ +#ifdef _LIBC + retval = __current_locale_name (category); +#else + retval = _nl_locale_name (category, categoryname); +#endif + + /* Ignore LANGUAGE 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". We allow such programs to use gettext(). */ + return language != NULL && strcmp (retval, "C") != 0 ? language : 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 + +#if !_LIBC && !HAVE_MEMPCPY +static void * +mempcpy (void *dest, const void *src, size_t n) +{ + return (void *) ((char *) memcpy (dest, src, n) + n); +} +#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 != INTUSE(_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/unix/intl/dcngettext.c b/unix/intl/dcngettext.c new file mode 100644 index 00000000..48a3e09e --- /dev/null +++ b/unix/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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/unix/intl/dgettext.c b/unix/intl/dgettext.c new file mode 100644 index 00000000..b64b0f5d --- /dev/null +++ b/unix/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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/unix/intl/dngettext.c b/unix/intl/dngettext.c new file mode 100644 index 00000000..7815637f --- /dev/null +++ b/unix/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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/unix/intl/eval-plural.h b/unix/intl/eval-plural.h new file mode 100644 index 00000000..01bd5af5 --- /dev/null +++ b/unix/intl/eval-plural.h @@ -0,0 +1,108 @@ +/* Plural expression evaluation. + Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#ifndef STATIC +#define STATIC static +#endif + +/* Evaluate the plural expression and return an index value. */ +STATIC +unsigned long int +internal_function +plural_eval (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/unix/intl/explodename.c b/unix/intl/explodename.c new file mode 100644 index 00000000..52c25e72 --- /dev/null +++ b/unix/intl/explodename.c @@ -0,0 +1,185 @@ +/* Copyright (C) 1995-1998, 2000-2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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 @@ */ + +char * +_nl_find_language (const char *name) +{ + while (name[0] != '\0' && name[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, const char **special, + const char **sponsor, const char **revision) +{ + enum { undecided, xpg, cen } syntax; + char *cp; + int mask; + + *modifier = NULL; + *territory = NULL; + *codeset = NULL; + *normalized_codeset = NULL; + *special = NULL; + *sponsor = NULL; + *revision = NULL; + + /* Now we determine the single parts of the locale name. First + look for the language. Termination symbols are `_' and `@' if + we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */ + mask = 0; + syntax = undecided; + *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[0] != '+' && cp[0] != ',' && cp[0] != '_') + ++cp; + + mask |= TERRITORY; + + if (cp[0] == '.') + { + /* Next is the codeset. */ + syntax = xpg; + 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 (strcmp (*codeset, *normalized_codeset) == 0) + free ((char *) *normalized_codeset); + else + mask |= XPG_NORM_CODESET; + } + } + } + + if (cp[0] == '@' || (syntax != xpg && cp[0] == '+')) + { + /* Next is the modifier. */ + syntax = cp[0] == '@' ? xpg : cen; + cp[0] = '\0'; + *modifier = ++cp; + + while (syntax == cen && cp[0] != '\0' && cp[0] != '+' + && cp[0] != ',' && cp[0] != '_') + ++cp; + + mask |= XPG_MODIFIER | CEN_AUDIENCE; + } + + if (syntax != xpg && (cp[0] == '+' || cp[0] == ',' || cp[0] == '_')) + { + syntax = cen; + + if (cp[0] == '+') + { + /* Next is special application (CEN syntax). */ + cp[0] = '\0'; + *special = ++cp; + + while (cp[0] != '\0' && cp[0] != ',' && cp[0] != '_') + ++cp; + + mask |= CEN_SPECIAL; + } + + if (cp[0] == ',') + { + /* Next is sponsor (CEN syntax). */ + cp[0] = '\0'; + *sponsor = ++cp; + + while (cp[0] != '\0' && cp[0] != '_') + ++cp; + + mask |= CEN_SPONSOR; + } + + if (cp[0] == '_') + { + /* Next is revision (CEN syntax). */ + cp[0] = '\0'; + *revision = ++cp; + + mask |= CEN_REVISION; + } + } + + /* For CEN syntax values it might be important to have the + separator character in the file name, not for XPG syntax. */ + if (syntax == xpg) + { + if (*territory != NULL && (*territory)[0] == '\0') + mask &= ~TERRITORY; + + if (*codeset != NULL && (*codeset)[0] == '\0') + mask &= ~XPG_CODESET; + + if (*modifier != NULL && (*modifier)[0] == '\0') + mask &= ~XPG_MODIFIER; + } + + return mask; +} diff --git a/unix/intl/finddomain.c b/unix/intl/finddomain.c new file mode 100644 index 00000000..4992a8c9 --- /dev/null +++ b/unix/intl/finddomain.c @@ -0,0 +1,192 @@ +/* Handle list of needed message catalogs + Copyright (C) 1995-1999, 2000-2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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 + +/* @@ 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 *special; + const char *sponsor; + const char *revision; + const char *alias_value; + int mask; + + /* LOCALE can consist of up to four recognized parts for the XPG syntax: + + language[_territory[.codeset]][@modifier] + + and six parts for the CEN syntax: + + language[_territory][+audience][+special][,[sponsor][_revision]] + + 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) revision + (2) sponsor + (3) special + (4) codeset + (5) normalized codeset + (6) territory + (7) audience/modifier + */ + + /* 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, NULL, NULL, NULL, domainname, 0); + 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 cnt >= 0 ? retval : NULL; + /* 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 `@' if + we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */ + mask = _nl_explode_name (locale, &language, &modifier, &territory, + &codeset, &normalized_codeset, &special, + &sponsor, &revision); + + /* 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, special, + sponsor, revision, domainname, 1); + if (retval == NULL) + /* This means we are out of core. */ + return NULL; + + 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); + + /* The space for normalized_codeset is dynamically allocated. Free it. */ + if (mask & XPG_NORM_CODESET) + free ((void *) normalized_codeset); + + return retval; +} + + +#ifdef _LIBC +libc_freeres_fn (free_mem) +{ + 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/unix/intl/gettext.c b/unix/intl/gettext.c new file mode 100644 index 00000000..92c42faa --- /dev/null +++ b/unix/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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/unix/intl/gettext.h b/unix/intl/gettext.h new file mode 100644 index 00000000..8b262f4c --- /dev/null +++ b/unix/intl/gettext.h @@ -0,0 +1,69 @@ +/* Convenience header for conditional use of GNU . + Copyright (C) 1995-1998, 2000-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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#ifndef _LIBGETTEXT_H +#define _LIBGETTEXT_H 1 + +/* NLS can be disabled through the configure --disable-nls option. */ +#if ENABLE_NLS + +/* Get declarations of GNU message catalog functions. */ +# include + +#else + +/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which + chokes if dcgettext is defined as a macro. So include it now, to make + later inclusions of a NOP. We don't include + as well because people using "gettext.h" will not include , + and also including would fail on SunOS 4, whereas + is OK. */ +#if defined(__sun) +# include +#endif + +/* Disabled NLS. + The casts to 'const char *' serve the purpose of producing warnings + for invalid uses of the value returned from these functions. + On pre-ANSI systems without 'const', the config.h file is supposed to + contain "#define const". */ +# define gettext(Msgid) ((const char *) (Msgid)) +# define dgettext(Domainname, Msgid) ((const char *) (Msgid)) +# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define textdomain(Domainname) ((const char *) (Domainname)) +# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) +# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) + +#endif + +/* A pseudo function call that serves as a marker for the automated + extraction of messages, but does not call gettext(). The run-time + translation is done at a different place in the code. + The argument, String, should be a literal string. Concatenated strings + and other string expressions won't work. + The macro's expansion is not parenthesized, so that it is suitable as + initializer for static 'char[]' or 'const char[]' variables. */ +#define gettext_noop(String) String + +#endif /* _LIBGETTEXT_H */ diff --git a/unix/intl/gettextP.h b/unix/intl/gettextP.h new file mode 100644 index 00000000..4d66c3de --- /dev/null +++ b/unix/intl/gettextP.h @@ -0,0 +1,215 @@ +/* Header describing internals of libintl library. + Copyright (C) 1995-1999, 2000-2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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 + +#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 +SWAP (i) + nls_uint32 i; +{ + 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; +}; + +/* 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; + + int codeset_cntr; +#ifdef _LIBC + __gconv_t conv; +#else +# if HAVE_ICONV + iconv_t conv; +# endif +#endif + char **conv_tab; + + 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; + int codeset_cntr; /* Incremented each time codeset changes. */ + 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. */ +extern int _nl_msg_cat_cntr; + +#ifndef _LIBC +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; +void _nl_unload_domain (struct loaded_domain *__domain) + internal_function; +const char *_nl_init_domain_conv (struct loaded_l10nfile *__domain_file, + struct loaded_domain *__domain, + struct binding *__domainbinding) + internal_function; +void _nl_free_domain_conv (struct loaded_domain *__domain) + internal_function; + +char *_nl_find_msg (struct loaded_l10nfile *domain_file, + struct binding *domainbinding, const char *msgid, + size_t *lengthp) + internal_function; + +#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); +#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" +extern char *libintl_dcigettext (const char *__domainname, + const char *__msgid1, const char *__msgid2, + int __plural, unsigned long int __n, + int __category); +#endif + +/* @@ begin of epilog @@ */ + +#endif /* gettextP.h */ diff --git a/unix/intl/gmo.h b/unix/intl/gmo.h new file mode 100644 index 00000000..e7c9cc14 --- /dev/null +++ b/unix/intl/gmo.h @@ -0,0 +1,149 @@ +/* Description of GNU message catalog format: general file layout. + Copyright (C) 1995, 1997, 2000-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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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; +}; + +/* 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 + { + /* Size of static segment. */ + nls_uint32 segsize; + /* Reference to system dependent string segment, or ~0 at the end. */ + nls_uint32 sysdepref; + } 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/unix/intl/hash-string.h b/unix/intl/hash-string.h new file mode 100644 index 00000000..093e3b1c --- /dev/null +++ b/unix/intl/hash-string.h @@ -0,0 +1,48 @@ +/* Description of GNU message catalog format: string hashing function. + Copyright (C) 1995, 1997-1998, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +/* @@ end of prolog @@ */ + +/* We assume to have `unsigned long int' value with at least 32 bits. */ +#define HASHWORDBITS 32 + + +/* 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.] */ +static inline 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/unix/intl/intl-compat.c b/unix/intl/intl-compat.c new file mode 100644 index 00000000..96f9d955 --- /dev/null +++ b/unix/intl/intl-compat.c @@ -0,0 +1,131 @@ +/* intl-compat.c - Stub functions to call gettext functions from GNU gettext + Library. + Copyright (C) 1995, 2000-2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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 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/unix/intl/l10nflist.c b/unix/intl/l10nflist.c new file mode 100644 index 00000000..eb995aaf --- /dev/null +++ b/unix/intl/l10nflist.c @@ -0,0 +1,421 @@ +/* Copyright (C) 1995-1999, 2000-2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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 __EMX__ || defined __DJGPP__ + /* Win32, 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. */ + +#if !defined _LIBC && !defined HAVE___ARGZ_COUNT +/* 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) +#else +# ifdef _LIBC +# define __argz_count(argz, len) INTUSE(__argz_count) (argz, len) +# endif +#endif /* !_LIBC && !HAVE___ARGZ_COUNT */ + +#if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY +/* 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) +#else +# ifdef _LIBC +# define __argz_stringify(argz, len, sep) \ + INTUSE(__argz_stringify) (argz, len, sep) +# endif +#endif /* !_LIBC && !HAVE___ARGZ_STRINGIFY */ + +#if !defined _LIBC && !defined HAVE___ARGZ_NEXT +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 *special, + const char *sponsor, const char *revision, + 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 & 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 + || (mask & CEN_AUDIENCE) != 0) + ? strlen (modifier) + 1 : 0) + + ((mask & CEN_SPECIAL) != 0 + ? strlen (special) + 1 : 0) + + (((mask & CEN_SPONSOR) != 0 + || (mask & CEN_REVISION) != 0) + ? (1 + ((mask & CEN_SPONSOR) != 0 + ? strlen (sponsor) : 0) + + ((mask & CEN_REVISION) != 0 + ? strlen (revision) + 1 : 0)) : 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 & 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 | CEN_AUDIENCE)) != 0) + { + /* This component can be part of both syntaces but has different + leading characters. For CEN we use `+', else `@'. */ + *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@'; + cp = stpcpy (cp, modifier); + } + if ((mask & CEN_SPECIAL) != 0) + { + *cp++ = '+'; + cp = stpcpy (cp, special); + } + if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0) + { + *cp++ = ','; + if ((mask & CEN_SPONSOR) != 0) + cp = stpcpy (cp, sponsor); + if ((mask & CEN_REVISION) != 0) + { + *cp++ = '_'; + cp = stpcpy (cp, revision); + } + } + + *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) + 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 & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 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, special, + sponsor, revision, filename, 1); + } + else + retval->successor[entries++] + = _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, + cnt, language, territory, codeset, + normalized_codeset, modifier, special, + sponsor, revision, 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/unix/intl/libgnuintl.h.in b/unix/intl/libgnuintl.h.in new file mode 100644 index 00000000..3be7eb99 --- /dev/null +++ b/unix/intl/libgnuintl.h.in @@ -0,0 +1,383 @@ +/* Message catalogs for internationalization. + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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 ? 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 + + +/* 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 && !defined __APPLE_CC__ && !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 + +/* 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); +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); +#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); +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); +#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); +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); +#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); +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); +#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); +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); +#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); +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); +#endif + + +/* 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 + + +/* 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 +#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/unix/intl/loadinfo.h b/unix/intl/loadinfo.h new file mode 100644 index 00000000..65e5ebd1 --- /dev/null +++ b/unix/intl/loadinfo.h @@ -0,0 +1,145 @@ +/* Copyright (C) 1996-1999, 2000-2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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 + +/* 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 __EMX__ || defined __DJGPP__ + /* Win32, OS/2, DOS */ +# define PATH_SEPARATOR ';' +#else + /* Unix */ +# define PATH_SEPARATOR ':' +#endif + +/* Encoding of locale name parts. */ +#define CEN_REVISION 1 +#define CEN_SPONSOR 2 +#define CEN_SPECIAL 4 +#define XPG_NORM_CODESET 8 +#define XPG_CODESET 16 +#define TERRITORY 32 +#define CEN_AUDIENCE 64 +#define XPG_MODIFIER 128 + +#define CEN_SPECIFIC (CEN_REVISION|CEN_SPONSOR|CEN_SPECIAL|CEN_AUDIENCE) +#define XPG_SPECIFIC (XPG_CODESET|XPG_NORM_CODESET|XPG_MODIFIER) + + +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, + SPECIAL, SPONSOR, REVISION 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 *special, + const char *sponsor, const char *revision, + 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. */ +extern const char *_nl_expand_alias (const char *name); + +/* Split a locale name NAME into its pieces: language, modifier, + territory, codeset, special, sponsor, revision. + NAME gets destructively modified: NUL bytes are inserted here and + there. *LANGUAGE gets assigned NAME. Each of *MODIFIER, *TERRITORY, + *CODESET, *SPECIAL, *SPONSOR, *REVISION 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, CEN_AUDIENCE for *MODIFIER, + TERRITORY for *TERRITORY, + XPG_CODESET for *CODESET, + XPG_NORM_CODESET for *NORMALIZED_CODESET, + CEN_SPECIAL for *SPECIAL, + CEN_SPONSOR for *SPONSOR, + CEN_REVISION for *REVISION. + */ +extern int _nl_explode_name (char *name, const char **language, + const char **modifier, const char **territory, + const char **codeset, + const char **normalized_codeset, + const char **special, const char **sponsor, + const char **revision); + +/* 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. */ +extern char *_nl_find_language (const char *name); + +#endif /* loadinfo.h */ diff --git a/unix/intl/loadmsgcat.c b/unix/intl/loadmsgcat.c new file mode 100644 index 00000000..99c51b4c --- /dev/null +++ b/unix/intl/loadmsgcat.c @@ -0,0 +1,1420 @@ +/* Load needed message catalogs. + Copyright (C) 1995-1999, 2000-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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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" +#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 __open +# define close __close +# define read __read +# define mmap __mmap +# define munmap __munmap +#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; +} + +/* Initialize the codeset dependent parts of an opened message catalog. + Return the header entry. */ +const char * +internal_function +_nl_init_domain_conv (struct loaded_l10nfile *domain_file, + struct loaded_domain *domain, + struct binding *domainbinding) +{ + /* 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. */ + char *nullentry; + size_t nullentrylen; + + /* Preinitialize fields, to avoid recursion during _nl_find_msg. */ + domain->codeset_cntr = + (domainbinding != NULL ? domainbinding->codeset_cntr : 0); +#ifdef _LIBC + domain->conv = (__gconv_t) -1; +#else +# if HAVE_ICONV + domain->conv = (iconv_t) -1; +# endif +#endif + domain->conv_tab = NULL; + + /* Get the header entry. */ + nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen); + + if (nullentry != NULL) + { +#if defined _LIBC || HAVE_ICONV + 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 + + /* 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. Moreover, the value specified through + bind_textdomain_codeset overrides both. */ + if (domainbinding != NULL && domainbinding->codeset != NULL) + outcharset = domainbinding->codeset; + else + { + outcharset = getenv ("OUTPUT_CHARSET"); + if (outcharset == NULL || outcharset[0] == '\0') + { +# ifdef _LIBC + outcharset = _NL_CURRENT (LC_CTYPE, CODESET); +# else +# if HAVE_ICONV + extern const char *locale_charset (void); + outcharset = locale_charset (); +# endif +# endif + } + } + +# ifdef _LIBC + /* We always want to use transliteration. */ + outcharset = norm_add_slashes (outcharset, "TRANSLIT"); + charset = norm_add_slashes (charset, NULL); + if (__gconv_open (outcharset, charset, &domain->conv, + GCONV_AVOID_NOCONV) + != __GCONV_OK) + domain->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; + + domain->conv = iconv_open (outcharset, charset); + + freea (outcharset); + } + else +# endif + domain->conv = iconv_open (outcharset, charset); +# endif +# endif + + freea (charset); + } +#endif /* _LIBC || HAVE_ICONV */ + } + + return nullentry; +} + +/* Frees the codeset dependent parts of an opened message catalog. */ +void +internal_function +_nl_free_domain_conv (struct loaded_domain *domain) +{ + if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1) + free (domain->conv_tab); + +#ifdef _LIBC + if (domain->conv != (__gconv_t) -1) + __gconv_close (domain->conv); +#else +# if HAVE_ICONV + if (domain->conv != (iconv_t) -1) + iconv_close (domain->conv); +# endif +#endif +} + +/* 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) +{ + int fd; + 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; + + 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) + return; + + /* Try to open the addressed file. */ + fd = open (domain_file->filename, O_RDONLY | O_BINARY); + if (fd == -1) + return; + + /* 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. */ + close (fd); + return; + } + +#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); + 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) + return; + + 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 + close (fd); + return; + } + read_ptr += nb; + to_read -= nb; + } + while (to_read > 0); + + close (fd); + } + + /* 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); + return; + } + + domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain)); + if (domain == NULL) + return; + 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 = + 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; + return; + } + + /* Now initialize the character set converter from the character set + the file is encoded with (found in the header entry) to the domain's + specified character set or the locale's character set. */ + nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding); + + /* Also look for a plural specification. */ + EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals); +} + + +#ifdef _LIBC +void +internal_function +_nl_unload_domain (struct loaded_domain *domain) +{ + if (domain->plural != &__gettext_germanic_plural) + __gettext_free_exp (domain->plural); + + _nl_free_domain_conv (domain); + + 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/unix/intl/localcharset.c b/unix/intl/localcharset.c new file mode 100644 index 00000000..4865f103 --- /dev/null +++ b/unix/intl/localcharset.c @@ -0,0 +1,398 @@ +/* Determine a canonical name for the current locale's character encoding. + + Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +/* Written by Bruno Haible . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* Specification. */ +#include "localcharset.h" + +#if HAVE_STDDEF_H +# include +#endif + +#include +#if HAVE_STRING_H +# include +#else +# include +#endif +#if HAVE_STDLIB_H +# include +#endif + +#if defined _WIN32 || defined __WIN32__ +# undef WIN32 /* avoid warning on mingw32 */ +# define WIN32 +#endif + +#if defined __EMX__ +/* Assume EMX program runs on OS/2, even if compiled under DOS. */ +# define OS2 +#endif + +#if !defined WIN32 +# if HAVE_LANGINFO_CODESET +# include +# else +# if HAVE_SETLOCALE +# include +# endif +# endif +#elif defined WIN32 +# 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 + +#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ + /* Win32, 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 () +{ + const char *cp; + + cp = charset_aliases; + if (cp == NULL) + { +#if !(defined VMS || defined WIN32) + FILE *fp; + const char *dir = relocate (LIBDIR); + const char *base = "charset.alias"; + char *file_name; + + /* 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. */ + int c; + char buf1[50+1]; + char buf2[50+1]; + char *res_ptr = NULL; + size_t res_size = 0; + size_t l1, l2; + + for (;;) + { + 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); + 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; + 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 + /* 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" + "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"; +# 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 () +{ + const char *codeset; + const char *aliases; + +#if !(defined WIN32 || defined OS2) + +# if HAVE_LANGINFO_CODESET + + /* Most systems support nl_langinfo (CODESET) nowadays. */ + codeset = nl_langinfo (CODESET); + +# 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 HAVE_SETLOCALE && 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 + + 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/unix/intl/localcharset.h b/unix/intl/localcharset.h new file mode 100644 index 00000000..3b137e73 --- /dev/null +++ b/unix/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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/unix/intl/locale.alias b/unix/intl/locale.alias new file mode 100644 index 00000000..bd6bb256 --- /dev/null +++ b/unix/intl/locale.alias @@ -0,0 +1,78 @@ +# Locale name alias data base. +# Copyright (C) 1996-2001,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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# 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 far from being complete. If you have a value for +# your own site which you think might be useful for others too, share +# it with the rest of us. Send it using the `glibcbug' script to +# bugs@gnu.org. + +# 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/unix/intl/localealias.c b/unix/intl/localealias.c new file mode 100644 index 00000000..2eaf8813 --- /dev/null +++ b/unix/intl/localealias.c @@ -0,0 +1,414 @@ +/* Handle aliases for locale names. + Copyright (C) 1995-1999, 2000-2001, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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 + +/* We need locking here since we can be called from different places. */ +# include + +__libc_lock_define_initialized (static, lock); +#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 + + +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; + +#ifdef _LIBC + __libc_lock_lock (lock); +#endif + + 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); + +#ifdef _LIBC + __libc_lock_unlock (lock); +#endif + + 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 + + fp = fopen (relocate (full_fname), "r"); + 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; + + if (FGETS (buf, sizeof buf, fp) == NULL) + /* EOF reached. */ + break; + + 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') + { + size_t alias_len; + size_t value_len; + + 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'; + + if (nmap >= maxmap) + if (__builtin_expect (extend_alias_table (), 0)) + return added; + + 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) + return added; + + 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 = memcpy (&string_space[string_space_act], + alias, alias_len); + string_space_act += alias_len; + + map[nmap].value = 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. */ + while (strchr (buf, '\n') == NULL) + 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; + } + + /* 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/unix/intl/localename.c b/unix/intl/localename.c new file mode 100644 index 00000000..5662e54f --- /dev/null +++ b/unix/intl/localename.c @@ -0,0 +1,1142 @@ +/* Determine the current selected locale. + Copyright (C) 1995-1999, 2000-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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +/* Written by Ulrich Drepper , 1995. */ +/* Win32 code written by Tor Lillqvist . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#if defined _WIN32 || defined __WIN32__ +# undef WIN32 /* avoid warning on mingw32 */ +# define WIN32 +#endif + +#ifdef WIN32 +# 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 0x00 +# endif +# ifndef SUBLANG_BENGALI_BANGLADESH +# define SUBLANG_BENGALI_BANGLADESH 0x01 +# 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 0x00 +# endif +# ifndef SUBLANG_PUNJABI_PAKISTAN +# define SUBLANG_PUNJABI_PAKISTAN 0x01 +# endif +# ifndef SUBLANG_ROMANIAN_ROMANIA +# define SUBLANG_ROMANIAN_ROMANIA 0x00 +# endif +# ifndef SUBLANG_ROMANIAN_MOLDOVA +# define SUBLANG_ROMANIAN_MOLDOVA 0x01 +# endif +# ifndef SUBLANG_SERBIAN_LATIN +# define SUBLANG_SERBIAN_LATIN 0x02 +# endif +# ifndef SUBLANG_SERBIAN_CYRILLIC +# define SUBLANG_SERBIAN_CYRILLIC 0x03 +# endif +# ifndef SUBLANG_SINDHI_INDIA +# define SUBLANG_SINDHI_INDIA 0x00 +# endif +# ifndef SUBLANG_SINDHI_PAKISTAN +# define SUBLANG_SINDHI_PAKISTAN 0x01 +# endif +# ifndef SUBLANG_SPANISH_GUATEMALA +# define SUBLANG_SPANISH_GUATEMALA 0x04 +# endif +# ifndef SUBLANG_SPANISH_COSTA_RICA +# define SUBLANG_SPANISH_COSTA_RICA 0x05 +# endif +# ifndef SUBLANG_SPANISH_PANAMA +# define SUBLANG_SPANISH_PANAMA 0x06 +# endif +# ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC +# define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07 +# endif +# ifndef SUBLANG_SPANISH_VENEZUELA +# define SUBLANG_SPANISH_VENEZUELA 0x08 +# endif +# ifndef SUBLANG_SPANISH_COLOMBIA +# define SUBLANG_SPANISH_COLOMBIA 0x09 +# endif +# ifndef SUBLANG_SPANISH_PERU +# define SUBLANG_SPANISH_PERU 0x0a +# endif +# ifndef SUBLANG_SPANISH_ARGENTINA +# define SUBLANG_SPANISH_ARGENTINA 0x0b +# endif +# ifndef SUBLANG_SPANISH_ECUADOR +# define SUBLANG_SPANISH_ECUADOR 0x0c +# endif +# ifndef SUBLANG_SPANISH_CHILE +# define SUBLANG_SPANISH_CHILE 0x0d +# endif +# ifndef SUBLANG_SPANISH_URUGUAY +# define SUBLANG_SPANISH_URUGUAY 0x0e +# endif +# ifndef SUBLANG_SPANISH_PARAGUAY +# define SUBLANG_SPANISH_PARAGUAY 0x0f +# endif +# ifndef SUBLANG_SPANISH_BOLIVIA +# define SUBLANG_SPANISH_BOLIVIA 0x10 +# endif +# ifndef SUBLANG_SPANISH_EL_SALVADOR +# define SUBLANG_SPANISH_EL_SALVADOR 0x11 +# endif +# ifndef SUBLANG_SPANISH_HONDURAS +# define SUBLANG_SPANISH_HONDURAS 0x12 +# endif +# ifndef SUBLANG_SPANISH_NICARAGUA +# define SUBLANG_SPANISH_NICARAGUA 0x13 +# endif +# ifndef SUBLANG_SPANISH_PUERTO_RICO +# define SUBLANG_SPANISH_PUERTO_RICO 0x14 +# endif +# ifndef SUBLANG_SWEDISH_FINLAND +# define SUBLANG_SWEDISH_FINLAND 0x02 +# endif +# ifndef SUBLANG_TAMAZIGHT_ARABIC +# define SUBLANG_TAMAZIGHT_ARABIC 0x01 +# endif +# ifndef SUBLANG_TAMAZIGHT_LATIN +# define SUBLANG_TAMAZIGHT_LATIN 0x02 +# endif +# ifndef SUBLANG_TIGRINYA_ETHIOPIA +# define SUBLANG_TIGRINYA_ETHIOPIA 0x00 +# endif +# ifndef SUBLANG_TIGRINYA_ERITREA +# define SUBLANG_TIGRINYA_ERITREA 0x01 +# endif +# ifndef SUBLANG_URDU_PAKISTAN +# define SUBLANG_URDU_PAKISTAN 0x01 +# endif +# ifndef SUBLANG_URDU_INDIA +# define SUBLANG_URDU_INDIA 0x02 +# endif +# ifndef SUBLANG_UZBEK_LATIN +# define SUBLANG_UZBEK_LATIN 0x01 +# endif +# ifndef SUBLANG_UZBEK_CYRILLIC +# define SUBLANG_UZBEK_CYRILLIC 0x02 +# endif +#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 __GNU_LIBRARY__ && __GNU_LIBRARY__ >= 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 * +_nl_locale_name (int category, const char *categoryname) +{ + const char *retval; + +#ifndef WIN32 + + /* 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 + retval = setlocale (category, NULL); +# else + /* Setting of LC_ALL overwrites all other. */ + retval = getenv ("LC_ALL"); + if (retval == NULL || retval[0] == '\0') + { + /* Next comes the name of the desired category. */ + retval = getenv (categoryname); + if (retval == NULL || retval[0] == '\0') + { + /* Last possibility is the LANG environment variable. */ + retval = getenv ("LANG"); + if (retval == NULL || retval[0] == '\0') + /* We use C as the default domain. POSIX says this is + implementation defined. */ + retval = "C"; + } + } +# endif + + return retval; + +#else /* WIN32 */ + + /* 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. */ + + LCID lcid; + LANGID langid; + int primary, sub; + + /* Let the user override the system settings through environment + variables, as on POSIX systems. */ + retval = getenv ("LC_ALL"); + if (retval != NULL && retval[0] != '\0') + return retval; + retval = getenv (categoryname); + if (retval != NULL && retval[0] != '\0') + return retval; + retval = getenv ("LANG"); + if (retval != NULL && retval[0] != '\0') + return retval; + + /* 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: + 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: + 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 "no_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: + 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_INDIA: return "sd_IN"; + case SUBLANG_SINDHI_PAKISTAN: return "sd_PK"; + } + 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_LATIN: return "ber_MA@latin"; + } + return "ber_MA"; + case LANG_TAMIL: + 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 +} diff --git a/unix/intl/log.c b/unix/intl/log.c new file mode 100644 index 00000000..cb6076e8 --- /dev/null +++ b/unix/intl/log.c @@ -0,0 +1,98 @@ +/* Log file output. + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +/* Written by Bruno Haible . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +/* 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); +} + +/* 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) +{ + static char *last_logfilename = NULL; + static FILE *last_logfile = NULL; + 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); +} diff --git a/unix/intl/ngettext.c b/unix/intl/ngettext.c new file mode 100644 index 00000000..e73e00c4 --- /dev/null +++ b/unix/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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/unix/intl/os2compat.c b/unix/intl/os2compat.c new file mode 100644 index 00000000..c8dc33e7 --- /dev/null +++ b/unix/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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/unix/intl/os2compat.h b/unix/intl/os2compat.h new file mode 100644 index 00000000..4f74e8c0 --- /dev/null +++ b/unix/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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/unix/intl/osdep.c b/unix/intl/osdep.c new file mode 100644 index 00000000..b3725983 --- /dev/null +++ b/unix/intl/osdep.c @@ -0,0 +1,24 @@ +/* OS dependent parts of libintl. + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#if defined __EMX__ +# include "os2compat.c" +#else +/* Avoid AIX compiler warning. */ +typedef int dummy; +#endif diff --git a/unix/intl/plural-exp.c b/unix/intl/plural-exp.c new file mode 100644 index 00000000..8c04e642 --- /dev/null +++ b/unix/intl/plural-exp.c @@ -0,0 +1,154 @@ +/* Expression parsing for plural form selection. + Copyright (C) 2000-2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#include "plural-exp.h" + +#if (defined __GNUC__ && !defined __APPLE_CC__) \ + || (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, 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/unix/intl/plural-exp.h b/unix/intl/plural-exp.h new file mode 100644 index 00000000..49e2c5bf --- /dev/null +++ b/unix/intl/plural-exp.h @@ -0,0 +1,118 @@ +/* Expression parsing and evaluation for plural form selection. + Copyright (C) 2000-2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#ifndef _PLURAL_EXP_H +#define _PLURAL_EXP_H + +#ifndef internal_function +# define internal_function +#endif + +#ifndef attribute_hidden +# define attribute_hidden +#endif + + +/* This is the representation of the expressions to determine the + plural form. */ +struct expression +{ + int nargs; /* Number of arguments. */ + enum 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. */ + } 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, + struct expression **pluralp, + unsigned long int *npluralsp) + internal_function; + +#if !defined (_LIBC) && !defined (IN_LIBINTL) +extern unsigned long int plural_eval (struct expression *pexp, + unsigned long int n); +#endif + +#endif /* _PLURAL_EXP_H */ diff --git a/unix/intl/plural.c b/unix/intl/plural.c new file mode 100644 index 00000000..72494f9e --- /dev/null +++ b/unix/intl/plural.c @@ -0,0 +1,1490 @@ +/* A Bison parser, made from plural.y + by GNU bison 1.35. */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define yyparse __gettextparse +#define yylex __gettextlex +#define yyerror __gettexterror +#define yylval __gettextlval +#define yychar __gettextchar +#define yydebug __gettextdebug +#define yynerrs __gettextnerrs +# define EQUOP2 257 +# define CMPOP2 258 +# define ADDOP2 259 +# define MULOP2 260 +# define NUMBER 261 + +#line 1 "plural.y" + +/* Expression parsing for plural form selection. + Copyright (C) 2000-2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +/* 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. */ +#if defined _AIX && !defined __GNUC__ + #pragma alloca +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#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 + +#line 49 "plural.y" +#ifndef YYSTYPE +typedef union { + unsigned long int num; + enum operator op; + struct expression *exp; +} yystype; +# define YYSTYPE yystype +# define YYSTYPE_IS_TRIVIAL 1 +#endif +#line 55 "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 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 operator op) +{ + return new_exp (0, op, NULL); +} + +static inline struct expression * +new_exp_1 (enum 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 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 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); +} + +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + + + +#define YYFINAL 27 +#define YYFLAG -32768 +#define YYNTBASE 16 + +/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */ +#define YYTRANSLATE(x) ((unsigned)(x) <= 261 ? yytranslate[x] : 18) + +/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */ +static const char 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, 6, 7, 8, + 9, 11 +}; + +#if YYDEBUG +static const short yyprhs[] = +{ + 0, 0, 2, 8, 12, 16, 20, 24, 28, 32, + 35, 37, 39 +}; +static const short yyrhs[] = +{ + 17, 0, 17, 3, 17, 12, 17, 0, 17, 4, + 17, 0, 17, 5, 17, 0, 17, 6, 17, 0, + 17, 7, 17, 0, 17, 8, 17, 0, 17, 9, + 17, 0, 10, 17, 0, 13, 0, 11, 0, 14, + 17, 15, 0 +}; + +#endif + +#if YYDEBUG +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const short yyrline[] = +{ + 0, 150, 158, 162, 166, 170, 174, 178, 182, 186, + 190, 194, 199 +}; +#endif + + +#if (YYDEBUG) || defined YYERROR_VERBOSE + +/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */ +static const char *const yytname[] = +{ + "$", "error", "$undefined.", "'?'", "'|'", "'&'", "EQUOP2", "CMPOP2", + "ADDOP2", "MULOP2", "'!'", "NUMBER", "':'", "'n'", "'('", "')'", + "start", "exp", 0 +}; +#endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const short yyr1[] = +{ + 0, 16, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const short yyr2[] = +{ + 0, 1, 5, 3, 3, 3, 3, 3, 3, 2, + 1, 1, 3 +}; + +/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE + doesn't specify something else to do. Zero means the default is an + error. */ +static const short yydefact[] = +{ + 0, 0, 11, 10, 0, 1, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 12, 0, 3, 4, 5, + 6, 7, 8, 0, 2, 0, 0, 0 +}; + +static const short yydefgoto[] = +{ + 25, 5 +}; + +static const short yypact[] = +{ + -9, -9,-32768,-32768, -9, 34,-32768, 11, -9, -9, + -9, -9, -9, -9, -9,-32768, 24, 39, 43, 16, + 26, -3,-32768, -9, 34, 21, 53,-32768 +}; + +static const short yypgoto[] = +{ + -32768, -1 +}; + + +#define YYLAST 53 + + +static const short yytable[] = +{ + 6, 1, 2, 7, 3, 4, 14, 16, 17, 18, + 19, 20, 21, 22, 8, 9, 10, 11, 12, 13, + 14, 26, 24, 12, 13, 14, 15, 8, 9, 10, + 11, 12, 13, 14, 13, 14, 23, 8, 9, 10, + 11, 12, 13, 14, 10, 11, 12, 13, 14, 11, + 12, 13, 14, 27 +}; + +static const short yycheck[] = +{ + 1, 10, 11, 4, 13, 14, 9, 8, 9, 10, + 11, 12, 13, 14, 3, 4, 5, 6, 7, 8, + 9, 0, 23, 7, 8, 9, 15, 3, 4, 5, + 6, 7, 8, 9, 8, 9, 12, 3, 4, 5, + 6, 7, 8, 9, 5, 6, 7, 8, 9, 6, + 7, 8, 9, 0 +}; +#define YYPURE 1 + +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/local/share/bison/bison.simple" + +/* Skeleton output parser for bison, + + Copyright (C) 1984, 1989, 1990, 2000, 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 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* This is the parser code that is written into each bison parser when + the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* 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. */ + +#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE) + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC malloc +# define YYSTACK_FREE free +# endif +#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short yyss; + YYSTYPE yyvs; +# if YYLSP_NEEDED + YYLTYPE yyls; +# endif +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# if YYLSP_NEEDED +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + + 2 * YYSTACK_GAP_MAX) +# else +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAX) +# endif + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (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_MAX; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#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 yyerrlab1 +/* 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); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror ("syntax error: cannot back up"); \ + YYERROR; \ + } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). + + When YYLLOC_DEFAULT is run, CURRENT is set the location of the + first token. By default, to implement support for ranges, extend + its range to the last symbol. */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current.last_line = Rhs[N].last_line; \ + Current.last_column = Rhs[N].last_column; +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#if YYPURE +# if YYLSP_NEEDED +# ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) +# else +# define YYLEX yylex (&yylval, &yylloc) +# endif +# else /* !YYLSP_NEEDED */ +# ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, YYLEX_PARAM) +# else +# define YYLEX yylex (&yylval) +# endif +# endif /* !YYLSP_NEEDED */ +#else /* !YYPURE */ +# define YYLEX yylex () +#endif /* !YYPURE */ + + +/* 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 (0) +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +#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 + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#if YYMAXDEPTH == 0 +# undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + +#ifdef YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# 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. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif +#endif + +#line 315 "/usr/local/share/bison/bison.simple" + + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +# define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +# define YYPARSE_PARAM_DECL +# else +# define YYPARSE_PARAM_ARG YYPARSE_PARAM +# define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +# endif +#else /* !YYPARSE_PARAM */ +# define YYPARSE_PARAM_ARG +# define YYPARSE_PARAM_DECL +#endif /* !YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +# ifdef YYPARSE_PARAM +int yyparse (void *); +# else +int yyparse (void); +# endif +#endif + +/* YY_DECL_VARIABLES -- depending whether we use a pure parser, + variables are global, or local to YYPARSE. */ + +#define YY_DECL_NON_LSP_VARIABLES \ +/* The lookahead symbol. */ \ +int yychar; \ + \ +/* The semantic value of the lookahead symbol. */ \ +YYSTYPE yylval; \ + \ +/* Number of parse errors so far. */ \ +int yynerrs; + +#if YYLSP_NEEDED +# define YY_DECL_VARIABLES \ +YY_DECL_NON_LSP_VARIABLES \ + \ +/* Location data for the lookahead symbol. */ \ +YYLTYPE yylloc; +#else +# define YY_DECL_VARIABLES \ +YY_DECL_NON_LSP_VARIABLES +#endif + + +/* If nonreentrant, generate the variables here. */ + +#if !YYPURE +YY_DECL_VARIABLES +#endif /* !YYPURE */ + +int +yyparse (YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + /* If reentrant, generate the variables here. */ +#if YYPURE + YY_DECL_VARIABLES +#endif /* !YYPURE */ + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yychar1 = 0; + + /* 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. */ + short yyssa[YYINITDEPTH]; + short *yyss = yyssa; + register short *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + +#if YYLSP_NEEDED + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; +#endif + +#if YYLSP_NEEDED +# define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +# define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + YYSIZE_T yystacksize = YYINITDEPTH; + + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; +#if YYLSP_NEEDED + YYLTYPE yyloc; +#endif + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + 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; +#if YYLSP_NEEDED + yylsp = yyls; +#endif + 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 (yyssp >= yyss + yystacksize - 1) + { + /* 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; + short *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. */ +# if YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yyls1, yysize * sizeof (*yylsp), + &yystacksize); + yyls = yyls1; +# else + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); +# endif + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + goto yyoverflowlab; + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + + { + short *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); +# if YYLSP_NEEDED + YYSTACK_RELOCATE (yyls); +# endif +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; +#if YYLSP_NEEDED + yylsp = yyls + yysize - 1; +#endif + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + 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. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yychar1 = YYTRANSLATE (yychar); + +#if YYDEBUG + /* We have to keep this `#if YYDEBUG', since we use variables + which are defined only if `YYDEBUG' is set. */ + if (yydebug) + { + YYFPRINTF (stderr, "Next token is %d (%s", + yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise + meaning of a token, for further debugging info. */ +# ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +# endif + YYFPRINTF (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + YYDPRINTF ((stderr, "Shifting token %d (%s), ", + yychar, yytname[yychar1])); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#if YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + 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 the semantic value of + the lookahead token. 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]; + +#if YYLSP_NEEDED + /* Similarly for the default location. Let the user run additional + commands if for instance locations are ranges. */ + yyloc = yylsp[1-yylen]; + YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); +#endif + +#if YYDEBUG + /* We have to keep this `#if YYDEBUG', since we use variables which + are defined only if `YYDEBUG' is set. */ + if (yydebug) + { + int yyi; + + YYFPRINTF (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++) + YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); + YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + switch (yyn) { + +case 1: +#line 151 "plural.y" +{ + if (yyvsp[0].exp == NULL) + YYABORT; + ((struct parse_args *) arg)->res = yyvsp[0].exp; + } + break; +case 2: +#line 159 "plural.y" +{ + yyval.exp = new_exp_3 (qmop, yyvsp[-4].exp, yyvsp[-2].exp, yyvsp[0].exp); + } + break; +case 3: +#line 163 "plural.y" +{ + yyval.exp = new_exp_2 (lor, yyvsp[-2].exp, yyvsp[0].exp); + } + break; +case 4: +#line 167 "plural.y" +{ + yyval.exp = new_exp_2 (land, yyvsp[-2].exp, yyvsp[0].exp); + } + break; +case 5: +#line 171 "plural.y" +{ + yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); + } + break; +case 6: +#line 175 "plural.y" +{ + yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); + } + break; +case 7: +#line 179 "plural.y" +{ + yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); + } + break; +case 8: +#line 183 "plural.y" +{ + yyval.exp = new_exp_2 (yyvsp[-1].op, yyvsp[-2].exp, yyvsp[0].exp); + } + break; +case 9: +#line 187 "plural.y" +{ + yyval.exp = new_exp_1 (lnot, yyvsp[0].exp); + } + break; +case 10: +#line 191 "plural.y" +{ + yyval.exp = new_exp_0 (var); + } + break; +case 11: +#line 195 "plural.y" +{ + if ((yyval.exp = new_exp_0 (num)) != NULL) + yyval.exp->val.num = yyvsp[0].num; + } + break; +case 12: +#line 200 "plural.y" +{ + yyval.exp = yyvsp[-1].exp; + } + break; +} + +#line 705 "/usr/local/share/bison/bison.simple" + + + yyvsp -= yylen; + yyssp -= yylen; +#if YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; +#if YYLSP_NEEDED + *++yylsp = yyloc; +#endif + + /* 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 - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + char *yymsg; + int yyx, yycount; + + yycount = 0; + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + if (yycheck[yyx + yyn] == yyx) + yysize += yystrlen (yytname[yyx]) + 15, yycount++; + yysize += yystrlen ("parse error, unexpected ") + 1; + yysize += yystrlen (yytname[YYTRANSLATE (yychar)]); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "parse error, unexpected "); + yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]); + + if (yycount < 5) + { + yycount = 0; + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); + yyx++) + if (yycheck[yyx + yyn] == yyx) + { + const char *yyq = ! yycount ? ", expecting " : " or "; + yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yytname[yyx]); + yycount++; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror ("parse error; also virtual memory exhausted"); + } + else +#endif /* defined (YYERROR_VERBOSE) */ + yyerror ("parse error"); + } + goto yyerrlab1; + + +/*--------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action | +`--------------------------------------------------*/ +yyerrlab1: + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + YYDPRINTF ((stderr, "Discarding token %d (%s).\n", + yychar, yytname[yychar1])); + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + + +/*-------------------------------------------------------------------. +| yyerrdefault -- current state does not do anything special for the | +| error token. | +`-------------------------------------------------------------------*/ +yyerrdefault: +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + + /* If its default is to accept any token, ok. Otherwise pop it. */ + yyn = yydefact[yystate]; + if (yyn) + goto yydefault; +#endif + + +/*---------------------------------------------------------------. +| yyerrpop -- pop the current state because it cannot handle the | +| error token | +`---------------------------------------------------------------*/ +yyerrpop: + if (yyssp == yyss) + YYABORT; + yyvsp--; + yystate = *--yyssp; +#if YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "Error: state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + +/*--------------. +| yyerrhandle. | +`--------------*/ +yyerrhandle: + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + + YYDPRINTF ((stderr, "Shifting error token, ")); + + *++yyvsp = yylval; +#if YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +/*---------------------------------------------. +| yyoverflowab -- parser overflow comes here. | +`---------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} +#line 205 "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/unix/intl/plural.y b/unix/intl/plural.y new file mode 100644 index 00000000..4d33bd7c --- /dev/null +++ b/unix/intl/plural.y @@ -0,0 +1,381 @@ +%{ +/* Expression parsing for plural form selection. + Copyright (C) 2000-2001, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +/* 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. */ +#if defined _AIX && !defined __GNUC__ + #pragma alloca +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#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 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 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 operator op) +{ + return new_exp (0, op, NULL); +} + +static inline struct expression * +new_exp_1 (enum 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 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 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/unix/intl/printf-args.c b/unix/intl/printf-args.c new file mode 100644 index 00000000..f6f3219e --- /dev/null +++ b/unix/intl/printf-args.c @@ -0,0 +1,119 @@ +/* Decomposed printf argument list. + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* Specification. */ +#include "printf-args.h" + +#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; +#ifdef HAVE_LONG_LONG + 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; +#ifdef HAVE_LONG_DOUBLE + case TYPE_LONGDOUBLE: + ap->a.a_longdouble = va_arg (args, long double); + break; +#endif + case TYPE_CHAR: + ap->a.a_char = va_arg (args, int); + break; +#ifdef HAVE_WINT_T + case TYPE_WIDE_CHAR: + ap->a.a_wide_char = va_arg (args, wint_t); + break; +#endif + case TYPE_STRING: + ap->a.a_string = va_arg (args, const char *); + break; +#ifdef HAVE_WCHAR_T + case TYPE_WIDE_STRING: + ap->a.a_wide_string = va_arg (args, const wchar_t *); + 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; +#ifdef HAVE_LONG_LONG + case TYPE_COUNT_LONGLONGINT_POINTER: + ap->a.a_count_longlongint_pointer = va_arg (args, long long int *); + break; +#endif + default: + /* Unknown type. */ + return -1; + } + return 0; +} diff --git a/unix/intl/printf-args.h b/unix/intl/printf-args.h new file mode 100644 index 00000000..f11e64c0 --- /dev/null +++ b/unix/intl/printf-args.h @@ -0,0 +1,137 @@ +/* Decomposed printf argument list. + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#ifndef _PRINTF_ARGS_H +#define _PRINTF_ARGS_H + +/* Get size_t. */ +#include + +/* Get wchar_t. */ +#ifdef HAVE_WCHAR_T +# include +#endif + +/* Get wint_t. */ +#ifdef 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, +#ifdef HAVE_LONG_LONG + TYPE_LONGLONGINT, + TYPE_ULONGLONGINT, +#endif + TYPE_DOUBLE, +#ifdef HAVE_LONG_DOUBLE + TYPE_LONGDOUBLE, +#endif + TYPE_CHAR, +#ifdef HAVE_WINT_T + TYPE_WIDE_CHAR, +#endif + TYPE_STRING, +#ifdef 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 +#ifdef HAVE_LONG_LONG +, TYPE_COUNT_LONGLONGINT_POINTER +#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; +#ifdef HAVE_LONG_LONG + long long int a_longlongint; + unsigned long long int a_ulonglongint; +#endif + float a_float; + double a_double; +#ifdef HAVE_LONG_DOUBLE + long double a_longdouble; +#endif + int a_char; +#ifdef HAVE_WINT_T + wint_t a_wide_char; +#endif + const char* a_string; +#ifdef 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; +#ifdef HAVE_LONG_LONG + long long int * a_count_longlongint_pointer; +#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/unix/intl/printf-parse.c b/unix/intl/printf-parse.c new file mode 100644 index 00000000..d19f903d --- /dev/null +++ b/unix/intl/printf-parse.c @@ -0,0 +1,537 @@ +/* Formatted output to strings. + Copyright (C) 1999-2000, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* Specification. */ +#if WIDE_CHAR_VERSION +# include "wprintf-parse.h" +#else +# include "printf-parse.h" +#endif + +/* Get size_t, NULL. */ +#include + +/* Get intmax_t. */ +#if HAVE_STDINT_H_WITH_UINTMAX +# include +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +# include +#endif + +/* malloc(), realloc(), free(). */ +#include + +/* Checked size_t computations. */ +#include "xsize.h" + +#if WIDE_CHAR_VERSION +# define PRINTF_PARSE wprintf_parse +# define CHAR_T wchar_t +# define DIRECTIVE wchar_t_directive +# define DIRECTIVES wchar_t_directives +#else +# define PRINTF_PARSE printf_parse +# define CHAR_T char +# define DIRECTIVE char_directive +# define DIRECTIVES char_directives +#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 = malloc (d_allocated * sizeof (DIRECTIVE)); + if (d->dir == NULL) + /* Out of memory. */ + return -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 error; \ + memory = (a->arg \ + ? realloc (a->arg, memory_size) \ + : malloc (memory_size)); \ + if (memory == NULL) \ + /* Out of memory. */ \ + goto error; \ + 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++; + } +#ifdef HAVE_INTMAX_T + 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++; + } +#endif + 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': +#ifdef HAVE_LONG_LONG + if (flags >= 16 || (flags & 4)) + type = TYPE_LONGLONGINT; + else +#endif + 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': +#ifdef HAVE_LONG_LONG + if (flags >= 16 || (flags & 4)) + type = TYPE_ULONGLONGINT; + else +#endif + 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': +#ifdef HAVE_LONG_DOUBLE + if (flags >= 16 || (flags & 4)) + type = TYPE_LONGDOUBLE; + else +#endif + type = TYPE_DOUBLE; + break; + case 'c': + if (flags >= 8) +#ifdef HAVE_WINT_T + type = TYPE_WIDE_CHAR; +#else + goto error; +#endif + else + type = TYPE_CHAR; + break; +#ifdef HAVE_WINT_T + case 'C': + type = TYPE_WIDE_CHAR; + c = 'c'; + break; +#endif + case 's': + if (flags >= 8) +#ifdef HAVE_WCHAR_T + type = TYPE_WIDE_STRING; +#else + goto error; +#endif + else + type = TYPE_STRING; + break; +#ifdef HAVE_WCHAR_T + case 'S': + type = TYPE_WIDE_STRING; + c = 's'; + break; +#endif + case 'p': + type = TYPE_POINTER; + break; + case 'n': +#ifdef HAVE_LONG_LONG + if (flags >= 16 || (flags & 4)) + type = TYPE_COUNT_LONGLONGINT_POINTER; + else +#endif + 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; + 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 error; + memory = realloc (d->dir, memory_size); + if (memory == NULL) + /* Out of memory. */ + goto error; + d->dir = memory; + } + } + } + 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); + return -1; +} + +#undef DIRECTIVES +#undef DIRECTIVE +#undef CHAR_T +#undef PRINTF_PARSE diff --git a/unix/intl/printf-parse.h b/unix/intl/printf-parse.h new file mode 100644 index 00000000..8aec50e2 --- /dev/null +++ b/unix/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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/unix/intl/printf.c b/unix/intl/printf.c new file mode 100644 index 00000000..878646c2 --- /dev/null +++ b/unix/intl/printf.c @@ -0,0 +1,371 @@ +/* Formatted output to strings, using POSIX/XSI format strings with positions. + Copyright (C) 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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 + +/* 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 + +/* 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) + { + if (fwrite (result, 1, length, stream) == length) + retval = length; + free (result); + } + 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; + } + 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) + { + if (length < maxlength) + abort (); + memcpy (resultbuf, result, maxlength - 1); + resultbuf[maxlength - 1] = '\0'; + } + free (result); + 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; + *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 + +/* Define auxiliary functions declared in "wprintf-parse.h". */ +#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; + if (i == length) + retval = length; + free (result); + } + 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) + { + if (length < maxlength) + abort (); + memcpy (resultbuf, result, (maxlength - 1) * sizeof (wchar_t)); + resultbuf[maxlength - 1] = 0; + } + free (result); + 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/unix/intl/ref-add.sin b/unix/intl/ref-add.sin new file mode 100644 index 00000000..167374e3 --- /dev/null +++ b/unix/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# 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/unix/intl/ref-del.sin b/unix/intl/ref-del.sin new file mode 100644 index 00000000..613cf37f --- /dev/null +++ b/unix/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. +# +# Written by Bruno Haible . +# +/^# Packages using this file: / { + s/# Packages using this file:// + s/ @PACKAGE@ / / + s/^/# Packages using this file:/ +} diff --git a/unix/intl/relocatable.c b/unix/intl/relocatable.c new file mode 100644 index 00000000..bf7c7085 --- /dev/null +++ b/unix/intl/relocatable.c @@ -0,0 +1,449 @@ +/* Provide relocatable packages. + Copyright (C) 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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 + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +/* 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__ +# 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 __EMX__ || defined __DJGPP__ + /* Win32, 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 FILESYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0) +#else + /* Unix */ +# define ISSLASH(C) ((C) == '/') +# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL) +# define FILESYSTEM_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 + FILESYSTEM_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 + FILESYSTEM_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; + } +#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ + /* Win32, 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__ + +/* 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; + + shared_library_fullname = strdup (location); + } + + return TRUE; +} + +#else /* Unix */ + +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 / Unix */ + +/* Return the full pathname of the current shared library. + Return NULL if unknown. + Guaranteed to work only on Linux and Woe32. */ +static char * +get_shared_library_fullname () +{ +#if !(defined _WIN32 || defined __WIN32__) + 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/unix/intl/relocatable.h b/unix/intl/relocatable.h new file mode 100644 index 00000000..48c5b71e --- /dev/null +++ b/unix/intl/relocatable.h @@ -0,0 +1,77 @@ +/* Provide relocatable packages. + Copyright (C) 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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 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/unix/intl/textdomain.c b/unix/intl/textdomain.c new file mode 100644 index 00000000..8745a843 --- /dev/null +++ b/unix/intl/textdomain.c @@ -0,0 +1,141 @@ +/* Implementation of the textdomain(3) function. + Copyright (C) 1995-1998, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#ifdef _LIBC +# include +#else +# include "libgnuintl.h" +#endif +#include "gettextP.h" + +#ifdef _LIBC +/* We have to handle multi-threaded applications. */ +# include +#else +/* Provide dummy implementation if this is outside glibc. */ +# define __libc_rwlock_define(CLASS, NAME) +# define __libc_rwlock_wrlock(NAME) +# define __libc_rwlock_unlock(NAME) +#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_default_domain libintl_nl_default_default_domain +# define _nl_current_default_domain libintl_nl_current_default_domain +#endif + +/* @@ end of prolog @@ */ + +/* 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; + + +/* 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. */ +__libc_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; + + __libc_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); + } + + __libc_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/unix/intl/vasnprintf.c b/unix/intl/vasnprintf.c new file mode 100644 index 00000000..8a62282d --- /dev/null +++ b/unix/intl/vasnprintf.c @@ -0,0 +1,887 @@ +/* vsprintf with automatic memory allocation. + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +/* 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 + +#ifdef HAVE_CONFIG_H +# include +#endif +#ifndef IN_LIBINTL +# include +#endif + +/* Specification. */ +#if WIDE_CHAR_VERSION +# include "vasnwprintf.h" +#else +# include "vasnprintf.h" +#endif + +#include /* snprintf(), sprintf() */ +#include /* abort(), malloc(), realloc(), free() */ +#include /* memcpy(), strlen() */ +#include /* errno */ +#include /* CHAR_BIT */ +#include /* DBL_MAX_EXP, LDBL_MAX_EXP */ +#if WIDE_CHAR_VERSION +# include "wprintf-parse.h" +#else +# include "printf-parse.h" +#endif + +/* Checked size_t computations. */ +#include "xsize.h" + +#ifdef HAVE_WCHAR_T +# ifdef HAVE_WCSLEN +# define local_wcslen wcslen +# else + /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid + a dependency towards this library, here is a local substitute. + Define this substitute only once, even if this file is included + twice in the same compilation unit. */ +# ifndef local_wcslen_defined +# define local_wcslen_defined 1 +static size_t +local_wcslen (const wchar_t *s) +{ + const wchar_t *ptr; + + for (ptr = s; *ptr != (wchar_t) 0; ptr++) + ; + return ptr - s; +} +# endif +# endif +#endif + +#if WIDE_CHAR_VERSION +# define VASNPRINTF vasnwprintf +# define CHAR_T wchar_t +# define DIRECTIVE wchar_t_directive +# define DIRECTIVES wchar_t_directives +# define PRINTF_PARSE wprintf_parse +# 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 +# define VASNPRINTF vasnprintf +# define CHAR_T char +# define DIRECTIVE char_directive +# define DIRECTIVES char_directives +# define PRINTF_PARSE printf_parse +# define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) +# if HAVE_DECL__SNPRINTF + /* Windows. */ +# define SNPRINTF _snprintf +# else + /* Unix. */ +# define SNPRINTF snprintf +# endif +#endif + +CHAR_T * +VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args) +{ + DIRECTIVES d; + arguments a; + + if (PRINTF_PARSE (format, &d, &a) < 0) + { + errno = EINVAL; + 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; + CHAR_T *buf; + CHAR_T *buf_malloced; + const CHAR_T *cp; + size_t i; + DIRECTIVE *dp; + /* Output string accumulator. */ + CHAR_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 (CHAR_T)) + { + buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T)); + buf_malloced = NULL; + } + else +#endif + { + size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T)); + if (size_overflow_p (buf_memsize)) + goto out_of_memory_1; + buf = (CHAR_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; \ + CHAR_T *memory; \ + \ + allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \ + if ((needed) > allocated) \ + allocated = (needed); \ + memory_size = xtimes (allocated, sizeof (CHAR_T)); \ + if (size_overflow_p (memory_size)) \ + goto out_of_memory; \ + if (result == resultbuf || result == NULL) \ + memory = (CHAR_T *) malloc (memory_size); \ + else \ + memory = (CHAR_T *) realloc (result, memory_size); \ + if (memory == NULL) \ + goto out_of_memory; \ + if (result == resultbuf && length > 0) \ + memcpy (memory, result, length * sizeof (CHAR_T)); \ + 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); + memcpy (result + length, cp, n * sizeof (CHAR_T)); + length = augmented_length; + } + 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; +#ifdef HAVE_LONG_LONG + case TYPE_COUNT_LONGLONGINT_POINTER: + *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length; + break; +#endif + default: + abort (); + } + } + else + { + arg_type type = a.arg[dp->arg_index].type; + CHAR_T *p; + unsigned int prefix_count; + int prefixes[2]; +#if !USE_SNPRINTF + size_t tmp_length; + CHAR_T tmpbuf[700]; + CHAR_T *tmp; + + /* Allocate a temporary buffer of sufficient size for calling + sprintf. */ + { + size_t width; + size_t precision; + + 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; + width = (arg < 0 ? (unsigned int) (-arg) : arg); + } + else + { + const CHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } + } + + 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; + precision = (arg < 0 ? 0 : arg); + } + else + { + const CHAR_T *digitp = dp->precision_start + 1; + + precision = 0; + do + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); + while (digitp != dp->precision_end); + } + } + + switch (dp->conversion) + { + + case 'd': case 'i': case 'u': +# ifdef HAVE_LONG_LONG + if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long long) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + else +# endif + if (type == TYPE_LONGINT || type == TYPE_ULONGINT) + tmp_length = + (unsigned int) (sizeof (unsigned long) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.30103 /* binary -> decimal */ + * 2 /* estimate for FLAG_GROUP */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + break; + + case 'o': +# ifdef HAVE_LONG_LONG + 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 */ + + 1; /* account for leading sign */ + 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 */ + + 1; /* account for leading sign */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.333334 /* binary -> octal */ + ) + + 1 /* turn floor into ceil */ + + 1; /* account for leading sign */ + break; + + case 'x': case 'X': +# ifdef HAVE_LONG_LONG + 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 */ + + 2; /* account for leading sign or alternate form */ + 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 */ + + 2; /* account for leading sign or alternate form */ + else + tmp_length = + (unsigned int) (sizeof (unsigned int) * CHAR_BIT + * 0.25 /* binary -> hexadecimal */ + ) + + 1 /* turn floor into ceil */ + + 2; /* account for leading sign or alternate form */ + break; + + case 'f': case 'F': +# ifdef HAVE_LONG_DOUBLE + 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 +# endif + 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': + case 'a': case 'A': + tmp_length = + 12; /* sign, decimal point, exponent etc. */ + tmp_length = xsum (tmp_length, precision); + break; + + case 'c': +# if defined HAVE_WINT_T && !WIDE_CHAR_VERSION + if (type == TYPE_WIDE_CHAR) + tmp_length = MB_CUR_MAX; + else +# endif + tmp_length = 1; + break; + + case 's': +# ifdef 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 (tmp_length < width) + tmp_length = width; + + tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ + } + + if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T)) + tmp = tmpbuf; + else + { + size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T)); + + if (size_overflow_p (tmp_memsize)) + /* Overflow, would lead to out of memory. */ + goto out_of_memory; + tmp = (CHAR_T *) malloc (tmp_memsize); + if (tmp == NULL) + /* Out of memory. */ + goto out_of_memory; + } +#endif + + /* Construct the format string for calling snprintf or + sprintf. */ + p = buf; + *p++ = '%'; + if (dp->flags & FLAG_GROUP) + *p++ = '\''; + if (dp->flags & FLAG_LEFT) + *p++ = '-'; + if (dp->flags & FLAG_SHOWSIGN) + *p++ = '+'; + if (dp->flags & FLAG_SPACE) + *p++ = ' '; + if (dp->flags & FLAG_ALT) + *p++ = '#'; + if (dp->flags & FLAG_ZERO) + *p++ = '0'; + if (dp->width_start != dp->width_end) + { + size_t n = dp->width_end - dp->width_start; + memcpy (p, dp->width_start, n * sizeof (CHAR_T)); + p += n; + } + if (dp->precision_start != dp->precision_end) + { + size_t n = dp->precision_end - dp->precision_start; + memcpy (p, dp->precision_start, n * sizeof (CHAR_T)); + p += n; + } + + switch (type) + { +#ifdef HAVE_LONG_LONG + case TYPE_LONGLONGINT: + case TYPE_ULONGLONGINT: + *p++ = 'l'; + /*FALLTHROUGH*/ +#endif + case TYPE_LONGINT: + case TYPE_ULONGINT: +#ifdef HAVE_WINT_T + case TYPE_WIDE_CHAR: +#endif +#ifdef HAVE_WCHAR_T + case TYPE_WIDE_STRING: +#endif + *p++ = 'l'; + break; +#ifdef HAVE_LONG_DOUBLE + case TYPE_LONGDOUBLE: + *p++ = 'L'; + break; +#endif + default: + break; + } + *p = dp->conversion; +#if USE_SNPRINTF + p[1] = '%'; + p[2] = 'n'; + p[3] = '\0'; +#else + p[1] = '\0'; +#endif + + /* Construct the arguments for calling snprintf or sprintf. */ + prefix_count = 0; + if (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 + /* Prepare checking whether snprintf returns the count + via %n. */ + ENSURE_ALLOCATION (xsum (length, 1)); + result[length] = '\0'; +#endif + + for (;;) + { + size_t maxlen; + int count; + int retcount; + + maxlen = allocated - length; + count = -1; + retcount = 0; + +#if USE_SNPRINTF +# define SNPRINTF_BUF(arg) \ + switch (prefix_count) \ + { \ + case 0: \ + retcount = SNPRINTF (result + length, maxlen, buf, \ + arg, &count); \ + break; \ + case 1: \ + retcount = SNPRINTF (result + length, maxlen, buf, \ + prefixes[0], arg, &count); \ + break; \ + case 2: \ + retcount = SNPRINTF (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; +#ifdef HAVE_LONG_LONG + 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; +#ifdef HAVE_LONG_DOUBLE + case TYPE_LONGDOUBLE: + { + long double arg = a.arg[dp->arg_index].a.a_longdouble; + SNPRINTF_BUF (arg); + } + break; +#endif + case TYPE_CHAR: + { + int arg = a.arg[dp->arg_index].a.a_char; + SNPRINTF_BUF (arg); + } + break; +#ifdef 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; +#ifdef 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 && result[length + count] != '\0') + abort (); + /* Portability hack. */ + if (retcount > count) + count = retcount; + } + else + { + /* snprintf() doesn't understand the '%n' + directive. */ + if (p[1] != '\0') + { + /* Don't use the '%n' directive; instead, look + at the snprintf() return value. */ + p[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 + if (count >= tmp_length) + /* tmp_length was incorrectly calculated - fix the + code above! */ + abort (); +#endif + + /* Make room for the result. */ + if (count >= maxlen) + { + /* Need at least count bytes. But allocate + proportionally, to avoid looping eternally if + snprintf() reports a too small count. */ + size_t n = + xmax (xsum (length, count), xtimes (allocated, 2)); + + ENSURE_ALLOCATION (n); +#if USE_SNPRINTF + continue; +#endif + } + +#if USE_SNPRINTF + /* The snprintf() result did fit. */ +#else + /* Append the sprintf() result. */ + memcpy (result + length, tmp, count * sizeof (CHAR_T)); + if (tmp != tmpbuf) + free (tmp); +#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. */ + CHAR_T *memory; + + memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T)); + if (memory != NULL) + result = memory; + } + + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + *lengthp = length; + return result; + + 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 SNPRINTF +#undef USE_SNPRINTF +#undef PRINTF_PARSE +#undef DIRECTIVES +#undef DIRECTIVE +#undef CHAR_T +#undef VASNPRINTF diff --git a/unix/intl/vasnprintf.h b/unix/intl/vasnprintf.h new file mode 100644 index 00000000..65f1bc13 --- /dev/null +++ b/unix/intl/vasnprintf.h @@ -0,0 +1,61 @@ +/* vsprintf 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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. */ +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/unix/intl/vasnwprintf.h b/unix/intl/vasnwprintf.h new file mode 100644 index 00000000..d3cef4cb --- /dev/null +++ b/unix/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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/unix/intl/wprintf-parse.h b/unix/intl/wprintf-parse.h new file mode 100644 index 00000000..24a2cfc2 --- /dev/null +++ b/unix/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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/unix/intl/xsize.h b/unix/intl/xsize.h new file mode 100644 index 00000000..362e24b7 --- /dev/null +++ b/unix/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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + 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/unix/mkinstalldirs b/unix/mkinstalldirs new file mode 100755 index 00000000..d2d5f21b --- /dev/null +++ b/unix/mkinstalldirs @@ -0,0 +1,111 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +errstatus=0 +dirmode="" + +usage="\ +Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." + +# process command line arguments +while test $# -gt 0 ; do + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" 1>&2 + exit 0 + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in + 0) exit 0 ;; +esac + +case $dirmode in + '') + if mkdir -p -- . 2>/dev/null; then + echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + fi + ;; + *) + if mkdir -m "$dirmode" -p -- . 2>/dev/null; then + echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + fi + ;; +esac + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + echo "chmod $dirmode $pathcomp" + lasterr="" + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# End: +# mkinstalldirs ends here diff --git a/unix/po/LINGUAS b/unix/po/LINGUAS new file mode 100644 index 00000000..19f8b860 --- /dev/null +++ b/unix/po/LINGUAS @@ -0,0 +1 @@ +sv de diff --git a/unix/po/Makefile.in.in b/unix/po/Makefile.in.in new file mode 100644 index 00000000..53efc5e1 --- /dev/null +++ b/unix/po/Makefile.in.in @@ -0,0 +1,366 @@ +# Makefile for PO directory in any package using GNU gettext. +# Copyright (C) 1995-1997, 2000-2004 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.14 + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SHELL = /bin/sh +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datadir = @datadir@ +localedir = $(datadir)/locale +gettextsrcdir = $(datadir)/gettext/po + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +mkinstalldirs = $(SHELL) $(MKINSTALLDIRS) + +GMSGFMT = @GMSGFMT@ +MSGFMT = @MSGFMT@ +XGETTEXT = @XGETTEXT@ +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 $(DOMAIN).pot stamp-po \ +$(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: all-@USE_NLS@ + +all-yes: stamp-po +all-no: + +# 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 -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) + @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 + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --msgid-bugs-address='$(MSGID_BUGS_ADDRESS)' + 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 \ + $(mkinstalldirs) $(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 + $(mkinstalldirs) $(DESTDIR)$(datadir) + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkinstalldirs) $(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 \ + $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ + else \ + : ; \ + fi +installdirs-data-no: +installdirs-data-yes: + $(mkinstalldirs) $(DESTDIR)$(datadir) + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkinstalldirs) $(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: $(DISTFILES) + dists="$(DISTFILES)"; \ + if test "$(PACKAGE)" = "gettext-tools"; then \ + dists="$$dists Makevars.template"; \ + 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); \ + else \ + cp -p $(srcdir)/$$file $(distdir); \ + 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 $(top_builddir)/config.status @POMAKEFILEDEPS@ + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \ + $(SHELL) ./config.status + +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/unix/po/Makevars b/unix/po/Makevars new file mode 100644 index 00000000..3458a757 --- /dev/null +++ b/unix/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_ --no-location + +# 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 = RealVNC Ltd, Constantin Kaplinsky, Peter Astrand, Cendio AB + +# 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 = devteam@tightvnc.com + +# 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/unix/po/POTFILES.in b/unix/po/POTFILES.in new file mode 100644 index 00000000..247f8d6d --- /dev/null +++ b/unix/po/POTFILES.in @@ -0,0 +1,12 @@ +# vncviewer_unix +vncviewer_unix/AboutDialog.h +vncviewer_unix/CConn.cxx +vncviewer_unix/CConn.h +vncviewer_unix/DesktopWindow.cxx +vncviewer_unix/DesktopWindow.h +vncviewer_unix/InfoDialog.h +vncviewer_unix/OptionsDialog.h +vncviewer_unix/parameters.h +vncviewer_unix/PasswdDialog.h +vncviewer_unix/ServerDialog.h +vncviewer_unix/vncviewer.cxx diff --git a/unix/po/Rules-quot b/unix/po/Rules-quot new file mode 100644 index 00000000..9c2a995e --- /dev/null +++ b/unix/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/unix/po/boldquot.sed b/unix/po/boldquot.sed new file mode 100644 index 00000000..4b937aa5 --- /dev/null +++ b/unix/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/unix/po/de.po b/unix/po/de.po new file mode 100644 index 00000000..36a74dd8 --- /dev/null +++ b/unix/po/de.po @@ -0,0 +1,191 @@ +# German translations for tightvnc package +# Deutsche Übersetzung für das Tightvnc Paket +# Copyright (C) 2005 RealVNC Ltd, Constantin Kaplinsky, Peter Astrand, Cendio AB +# Copyright (C) 2005 Klaus Franken, StrukturPunkt +# This file is distributed under the same license as the tightvnc package. +# Klaus Franken , 2005. +# +msgid "" +msgstr "" +"Project-Id-Version: tightvnc 1.5.0\n" +"Report-Msgid-Bugs-To: devteam@tightvnc.com\n" +"POT-Creation-Date: 2005-03-01 20:37+0100\n" +"PO-Revision-Date: 2005-03-01 20:41+0100\n" +"Last-Translator: Klaus Franken \n" +"Language-Team: German\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "About VNC Viewer" +msgstr "Über VNC-Viewer" + +msgid "VNC authentication" +msgstr "VNC Authentifizierung" + +msgid "Exit viewer" +msgstr "Viewer beenden" + +msgid "Full screen" +msgstr "Vollbild" + +msgid "Ctrl" +msgstr "Strg" + +msgid "Alt" +msgstr "Alt" + +#, c-format +msgid "Send %s" +msgstr "Sende %s" + +msgid "Send Ctrl-Alt-Del" +msgstr "Sende Strg-Alt-Del" + +msgid "Refresh screen" +msgstr "Bildschirm auffrischen" + +msgid "New connection..." +msgstr "Neue Verbindung..." + +msgid "Options..." +msgstr "Optionen..." + +msgid "Connection info..." +msgstr "Verbindungsinformationen..." + +msgid "About VNCviewer..." +msgstr "Über VNC-Viewer" + +msgid "Dismiss menu" +msgstr "Menü verlassen" + +msgid "VNC Menu" +msgstr "VNC-Menü" + +#, c-format +msgid "" +"Desktop name: %.80s\n" +"Host: %.80s port: %d\n" +"Size: %d x %d\n" +"Pixel format: %s\n" +"(server default %s)\n" +"Requested encoding: %s\n" +"Last used encoding: %s\n" +"Line speed estimate: %d kbit/s\n" +"Protocol version: %d.%d\n" +"Security method: %s\n" +msgstr "" +"Desktopname: %.80s\n" +"Host: %.80s port: %d\n" +"Größe: %d x %d\n" +"Pixelformat: %s\n" +"(Server Standard %s)\n" +"gewünschte Kodierung: %s\n" +"letzte benutzte Kodierung: %s\n" +"Leitungsgeschwindigkeit (geschätzt): %d kbit/s\n" +"Protokollversion: %d.%d\n" +"Sicherheitsmethode: %s\n" + +msgid "VNC connection info" +msgstr "VNC Verbindungsinformation" + +msgid "VNC Viewer: Connection Options" +msgstr "VNC-Viewer: Verbindungsoptionen" + +msgid "Encoding and Color Level:" +msgstr "Kodierung und Farbtiefe:" + +msgid "Inputs:" +msgstr "Eingaben:" + +msgid "Misc:" +msgstr "Diverses:" + +msgid "Auto select" +msgstr "automatische Auswahl" + +msgid "Full (all available colors)" +msgstr "Voll (alle verfügbaren Farben)" + +msgid "Medium (256 colors)" +msgstr "Mittel (256 Farben)" + +msgid "Low (64 colors)" +msgstr "Gering (64 Farben)" + +msgid "Very low (8 colors)" +msgstr "Sehr gering (8 Farben)" + +msgid "Custom compression level:" +msgstr "individueller Kompressionslevel:" + +msgid "level (1=fast, 9=best)" +msgstr "Level (1=schnell, 9=bester)" + +msgid "Allow JPEG compression:" +msgstr "Erlaube JPEG-Kompression:" + +msgid "quality (1=poor, 9=best)" +msgstr "Qualität (0=schlechte, 9=beste)" + +msgid "View only (ignore mouse & keyboard)" +msgstr "nur Ansicht (ignoriere Maus und Tastatur)" + +msgid "Accept clipboard from server" +msgstr "Akzeptiere Zwischenablage vom Server" + +msgid "Send clipboard to server" +msgstr "Sende Zwischenablage zum Server" + +msgid "Send primary selection & cut buffer as clipboard" +msgstr "Sende primary selection & cut buffer als Zwischenablage" + +msgid "Shared (don't disconnect other viewers)" +msgstr "Gemeinsamer Zugriff (andere VNC-Viewer nicht trennen)" + +msgid "Full-screen mode" +msgstr "Vollbild-Modus" + +msgid "Render cursor locally" +msgstr "Zeige Cursor lokal" + +msgid "Show dot when no cursor" +msgstr "Zeige Punkt wenn kein Cursor" + +msgid "OK" +msgstr "Ok" + +msgid "Cancel" +msgstr "Abbruch" + +msgid "Username:" +msgstr "Benutzername:" + +msgid "Password:" +msgstr "Passwort:" + +msgid "VNC Viewer: Connection Details" +msgstr "VNC-Viewer: Verbindungsdetails" + +msgid "VNC server:" +msgstr "VNC-Server:" + +msgid "About..." +msgstr "Über..." + +#, c-format +msgid "" +"TightVNC viewer for X version 4.0 - built %s\n" +"Copyright (C) 2002-2004 RealVNC Ltd.\n" +"Copyright (C) 2000-2004 Constantin Kaplinsky\n" +"Copyright (C) 2004-2005 Peter Astrand, Cendio AB\n" +"See http://www.tightvnc.com for information on TightVNC." +msgstr "" +"TightVNC-Viewer für X version 4.0 - gebaut %s\n" +"Copyright (C) 2002-2004 RealVNC Ltd.\n" +"Copyright (C) 2000-2004 Constantin Kaplinsky.\n" +"Copyright (C) 2004-2005 Peter Astrand, Cendio AB\n" +"Copyright (C) 2005 Klaus Franken, StrukturPunkt\n" +"Siehe http://www.tightvnc.com für Informationen über TightVNC." diff --git a/unix/po/en@boldquot.header b/unix/po/en@boldquot.header new file mode 100644 index 00000000..fedb6a06 --- /dev/null +++ b/unix/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/unix/po/en@quot.header b/unix/po/en@quot.header new file mode 100644 index 00000000..a9647fc3 --- /dev/null +++ b/unix/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/unix/po/insert-header.sin b/unix/po/insert-header.sin new file mode 100644 index 00000000..b26de01f --- /dev/null +++ b/unix/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/unix/po/quot.sed b/unix/po/quot.sed new file mode 100644 index 00000000..0122c463 --- /dev/null +++ b/unix/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/unix/po/remove-potcdate.sin b/unix/po/remove-potcdate.sin new file mode 100644 index 00000000..2436c49e --- /dev/null +++ b/unix/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/unix/po/ru.po b/unix/po/ru.po new file mode 100644 index 00000000..4b8bf807 --- /dev/null +++ b/unix/po/ru.po @@ -0,0 +1,188 @@ +# Russian translation for tightvnc package +# ãá᪨© ¯¥à¥¢®¤ ¯ ª¥â  tightvnc +# Copyright (C) 2005 RealVNC Ltd, Constantin Kaplinsky, Peter Astrand, Cendio AB +# This file is distributed under the same license as the tightvnc package. +# Constantin Kaplinsky , 2006. +# +msgid "" +msgstr "" +"Project-Id-Version: tightvnc 1.5.0\n" +"Report-Msgid-Bugs-To: devteam@tightvnc.com\n" +"POT-Creation-Date: 2005-03-01 20:37+0100\n" +"PO-Revision-Date: 2006-04-13 20:13+0700\n" +"Last-Translator: Constantin Kaplinsky \n" +"Language-Team: Russian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=KOI8-R\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "About VNC Viewer" +msgstr "Ž VNC Viewer" + +msgid "VNC authentication" +msgstr "€ã⥭â¨ä¨ª æ¨ï VNC" + +msgid "Exit viewer" +msgstr "‚ë室" + +msgid "Full screen" +msgstr "®«­®íªà ­­ë© ०¨¬" + +msgid "Ctrl" +msgstr "Ctrl" + +msgid "Alt" +msgstr "Alt" + +#, c-format +msgid "Send %s" +msgstr "®á« âì %s" + +msgid "Send Ctrl-Alt-Del" +msgstr "®á« âì Ctrl-Alt-Del" + +msgid "Refresh screen" +msgstr "Ž¡­®¢¨âì íªà ­" + +msgid "New connection..." +msgstr "®¢®¥ ᮥ¤¨­¥­¨¥..." + +msgid "Options..." +msgstr " à ¬¥âàë..." + +msgid "Connection info..." +msgstr "ˆ­ä®à¬ æ¨ï ® ᮥ¤¨­¥­¨¨..." + +msgid "About VNCviewer..." +msgstr "Ž VNC Viewer..." + +msgid "Dismiss menu" +msgstr "‡ ªàëâì ¬¥­î" + +msgid "VNC Menu" +msgstr "Œ¥­î VNC" + +#, c-format +msgid "" +"Desktop name: %.80s\n" +"Host: %.80s port: %d\n" +"Size: %d x %d\n" +"Pixel format: %s\n" +"(server default %s)\n" +"Requested encoding: %s\n" +"Last used encoding: %s\n" +"Line speed estimate: %d kbit/s\n" +"Protocol version: %d.%d\n" +"Security method: %s\n" +msgstr "" +"ˆ¬ï ᥠ­á : %.80s\n" +"Œ è¨­ : %.80s ¯®àâ: %d\n" +" §¬¥à: %d x %d\n" +"”®à¬ â 梥â : %s\n" +"(§­ ç¥­¨¥ á¥à¢¥à  %s)\n" +"‡ ¯à®è¥­­ ï á奬  ª®¤¨à®¢ ­¨ï: %s\n" +"®á«¥¤­ïï á奬  ª®¤¨à®¢ ­¨ï: %s\n" +"‘ª®à®áâì «¨­¨¨ á¢ï§¨: %d ª¡¨â/á\n" +"‚¥àá¨ï ¯à®â®ª®« : %d.%d\n" +"‘奬  ¡¥§®¯ á­®áâ¨: %s\n" + +msgid "VNC connection info" +msgstr "ˆ­ä®à¬ æ¨ï ® ᮥ¤¨­¥­¨¨ VNC" + +msgid "VNC Viewer: Connection Options" +msgstr "VNC Viewer: ¯ à ¬¥âàë ᮥ¤¨­¥­¨ï" + +msgid "Encoding and Color Level:" +msgstr "Š®¤¨à®¢ ­¨¥ ¨ 梥⮢®© ०¨¬:" + +msgid "Inputs:" +msgstr "‚¢®¤:" + +msgid "Misc:" +msgstr " §­®¥:" + +msgid "Auto select" +msgstr "€¢â®¬ â¨ç¥áª¨© ¢ë¡®à" + +msgid "Full (all available colors)" +msgstr "Œ­®£®æ¢¥â­ë© ०¨¬ (¢á¥ ¤®áâã¯­ë¥ æ¢¥â )" + +msgid "Medium (256 colors)" +msgstr "‘।­¥¥ ª ç¥á⢮ æ¢¥â  (256 梥⮢)" + +msgid "Low (64 colors)" +msgstr "¨§ª®¥ ª ç¥á⢮ æ¢¥â  (64 梥â )" + +msgid "Very low (8 colors)" +msgstr "Œ¨­¨¬ã¬ æ¢¥â  (8 梥⮢)" + +msgid "Custom compression level:" +msgstr "¥áâ ­¤ àâ­ë© ã஢¥­ì ᦠâ¨ï:" + +msgid "level (1=fast, 9=best)" +msgstr "ã஢¥­ì (1=¡ëáâà®, 9=¬ ªá.ᦠ⨥)" + +msgid "Allow JPEG compression:" +msgstr " §à¥è¨âì ᦠ⨥ JPEG:" + +msgid "quality (1=poor, 9=best)" +msgstr "ª ç¥á⢮ (1=­¨§ª®¥, 9=­ ¨«ãç襥)" + +msgid "View only (ignore mouse & keyboard)" +msgstr "’®«ìª® ¯à®á¬®âà (¨£­®à¨à®¢ âì ¬ëèì ¨ ª« ¢¨ âãàã)" + +msgid "Accept clipboard from server" +msgstr "à¨­¨¬ âì ¡ãä¥à ®¡¬¥­  á á¥à¢¥à " + +msgid "Send clipboard to server" +msgstr "®áë« âì ¡ãä¥à ®¡¬¥­  ­  á¥à¢¥à" + +msgid "Send primary selection & cut buffer as clipboard" +msgstr "®áë« âì \"primary selection\" ¨ \"cut buffer\" ª ª ¡ãä¥à ®¡¬¥­ " + +msgid "Shared (don't disconnect other viewers)" +msgstr " §¤¥«ï¥¬ë© ०¨¬ (­¥ ®âª«îç âì ¤àã£¨å ª«¨¥­â®¢)" + +msgid "Full-screen mode" +msgstr "®«­®íªà ­­ë© ०¨¬" + +msgid "Render cursor locally" +msgstr "¨á®¢ âì ªãàá®à «®ª «ì­®" + +msgid "Show dot when no cursor" +msgstr "®ª §ë¢ âì â®çªã ¯à¨ ®âáãâá⢨¨ ªãàá®à " + +msgid "OK" +msgstr "OK" + +msgid "Cancel" +msgstr "Žâ¬¥­ " + +msgid "Username:" +msgstr "ˆ¬ï ¯®«ì§®¢ â¥«ï:" + +msgid "Password:" +msgstr " à®«ì:" + +msgid "VNC Viewer: Connection Details" +msgstr "VNC Viewer: ¤¥â «¨ ᮥ¤¨­¥­¨ï" + +msgid "VNC server:" +msgstr "‘¥à¢¥à VNC:" + +msgid "About..." +msgstr "Ž ¯à®£à ¬¬¥..." + +#, c-format +msgid "" +"TightVNC viewer for X version 4.0 - built %s\n" +"Copyright (C) 2002-2004 RealVNC Ltd.\n" +"Copyright (C) 2000-2004 Constantin Kaplinsky\n" +"Copyright (C) 2004-2005 Peter Astrand, Cendio AB\n" +"See http://www.tightvnc.com for information on TightVNC." +msgstr "" +"TightVNC viewer ¤«ï X, ¢¥àá¨ï 4.0 - ¢à¥¬ï ᡮન %s\n" +"Copyright (C) 2002-2004 RealVNC Ltd.\n" +"Copyright (C) 2000-2004 Š®­á⠭⨭ Š ¯«¨­áª¨©\n" +"Copyright (C) 2004-2005 Peter Astrand, Cendio AB\n" +"ˆé¨â¥ ¨­ä®à¬ æ¨î ® TightVNC ­  ᠩ⥠http://www.tightvnc.com" diff --git a/unix/po/sv.po b/unix/po/sv.po new file mode 100644 index 00000000..a4988457 --- /dev/null +++ b/unix/po/sv.po @@ -0,0 +1,189 @@ +# Swedish translations for tightvnc package +# Svenska översättningar för paket tightvnc. +# Copyright (C) 2005 RealVNC Ltd, Constantin Kaplinsky, Peter Astrand, Cendio AB +# This file is distributed under the same license as the tightvnc package. +# Peter Astrand , 2005. +# +msgid "" +msgstr "" +"Project-Id-Version: tightvnc 1.5.0\n" +"Report-Msgid-Bugs-To: devteam@tightvnc.com\n" +"POT-Creation-Date: 2005-03-01 20:37+0100\n" +"PO-Revision-Date: 2005-03-01 20:39+0100\n" +"Last-Translator: Peter Astrand \n" +"Language-Team: Swedish\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "About VNC Viewer" +msgstr "Om VNC-visaren" + +msgid "VNC authentication" +msgstr "VNC-autentisering" + +msgid "Exit viewer" +msgstr "Avsluta visaren" + +msgid "Full screen" +msgstr "Fullskärm" + +msgid "Ctrl" +msgstr "Ctrl" + +msgid "Alt" +msgstr "Alt" + +#, c-format +msgid "Send %s" +msgstr "Skicka %s" + +msgid "Send Ctrl-Alt-Del" +msgstr "Skicka Ctrl-Alt-Del" + +msgid "Refresh screen" +msgstr "Uppdatera skärm" + +msgid "New connection..." +msgstr "Ny anslutning..." + +msgid "Options..." +msgstr "Inställningar..." + +msgid "Connection info..." +msgstr "Information om anslutningen..." + +msgid "About VNCviewer..." +msgstr "Om VNC-visaren..." + +msgid "Dismiss menu" +msgstr "Stäng meny" + +msgid "VNC Menu" +msgstr "VNC-meny" + +#, c-format +msgid "" +"Desktop name: %.80s\n" +"Host: %.80s port: %d\n" +"Size: %d x %d\n" +"Pixel format: %s\n" +"(server default %s)\n" +"Requested encoding: %s\n" +"Last used encoding: %s\n" +"Line speed estimate: %d kbit/s\n" +"Protocol version: %d.%d\n" +"Security method: %s\n" +msgstr "" +"Skrivbordsnamn: %.80s\n" +"Värd: %.80s port: %d\n" +"Storlek: %d x %d\n" +"Pixelformat: %s\n" +"(serverstandard %s)\n" +"Begärd kodning: %s\n" +"Senast använd kodning: %s\n" +"Uppskattad hastighet på förbindelsen: %d kbit/s\n" +"Protokollversion: %d.%d\n" +"Säkerhetsmetod: %s\n" + +msgid "VNC connection info" +msgstr "VNC anslutningsinformation" + +msgid "VNC Viewer: Connection Options" +msgstr "VNC-visare: Anslutningsalternativ" + +msgid "Encoding and Color Level:" +msgstr "Kodning och färgnivå:" + +msgid "Inputs:" +msgstr "Inmatning:" + +msgid "Misc:" +msgstr "Diverse:" + +msgid "Auto select" +msgstr "Automatiskt val" + +msgid "Full (all available colors)" +msgstr "Full (alla tillgängliga färger)" + +msgid "Medium (256 colors)" +msgstr "Medium (256 färger)" + +msgid "Low (64 colors)" +msgstr "Låg (64 färger)" + +msgid "Very low (8 colors)" +msgstr "Mycket låg (8 färger)" + +msgid "Custom compression level:" +msgstr "Anpassad kompressionsnivå:" + +msgid "level (1=fast, 9=best)" +msgstr "nivå (1=snabb, 9=bäst)" + +msgid "Allow JPEG compression:" +msgstr "Tillåt JPEG-kompression:" + +msgid "quality (1=poor, 9=best)" +msgstr "kvalitet (0=dålig, 9=bäst)" + +msgid "View only (ignore mouse & keyboard)" +msgstr "Endast visning (ignorera mus och tangentbord)" + +msgid "Accept clipboard from server" +msgstr "Acceptera urklipp från server" + +msgid "Send clipboard to server" +msgstr "Skicka urklipp till server" + +msgid "Send primary selection & cut buffer as clipboard" +msgstr "Skicka PRIMARY och CUT_BUFFER som urklipp" + +msgid "Shared (don't disconnect other viewers)" +msgstr "Delad (koppla ej från andra visare)" + +msgid "Full-screen mode" +msgstr "Fullskärmsläge" + +msgid "Render cursor locally" +msgstr "Hantera muspekaren lokalt" + +msgid "Show dot when no cursor" +msgstr "Visa punkt när muspekare saknas" + +msgid "OK" +msgstr "Ok" + +msgid "Cancel" +msgstr "Avbryt" + +msgid "Username:" +msgstr "Användarnamn:" + +msgid "Password:" +msgstr "Lösenord:" + +msgid "VNC Viewer: Connection Details" +msgstr "VNC-visare: Anslutningsdetaljer" + +msgid "VNC server:" +msgstr "VNC-server:" + +msgid "About..." +msgstr "Om..." + +#, c-format +msgid "" +"TightVNC viewer for X version 4.0 - built %s\n" +"Copyright (C) 2002-2004 RealVNC Ltd.\n" +"Copyright (C) 2000-2004 Constantin Kaplinsky\n" +"Copyright (C) 2004-2005 Peter Astrand, Cendio AB\n" +"See http://www.tightvnc.com for information on TightVNC." +msgstr "" +"TightVNC-visare för X version 4.0 - byggd %s\n" +"Copyright (C) 2002-2004 RealVNC Ltd.\n" +"Copyright (C) 2000-2004 Constantin Kaplinsky.\n" +"Copyright (C) 2004-2005 Peter Astrand, Cendio AB\n" +"Se http://www.tightvnc.com för information om TightVNC." diff --git a/unix/po/tightvnc.pot b/unix/po/tightvnc.pot new file mode 100644 index 00000000..c04c22ea --- /dev/null +++ b/unix/po/tightvnc.pot @@ -0,0 +1,173 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR RealVNC Ltd, Constantin Kaplinsky, Peter Astrand, Cendio AB +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: devteam@tightvnc.com\n" +"POT-Creation-Date: 2005-03-01 20:37+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "About VNC Viewer" +msgstr "" + +msgid "VNC authentication" +msgstr "" + +msgid "Exit viewer" +msgstr "" + +msgid "Full screen" +msgstr "" + +msgid "Ctrl" +msgstr "" + +msgid "Alt" +msgstr "" + +#, c-format +msgid "Send %s" +msgstr "" + +msgid "Send Ctrl-Alt-Del" +msgstr "" + +msgid "Refresh screen" +msgstr "" + +msgid "New connection..." +msgstr "" + +msgid "Options..." +msgstr "" + +msgid "Connection info..." +msgstr "" + +msgid "About VNCviewer..." +msgstr "" + +msgid "Dismiss menu" +msgstr "" + +msgid "VNC Menu" +msgstr "" + +#, c-format +msgid "" +"Desktop name: %.80s\n" +"Host: %.80s port: %d\n" +"Size: %d x %d\n" +"Pixel format: %s\n" +"(server default %s)\n" +"Requested encoding: %s\n" +"Last used encoding: %s\n" +"Line speed estimate: %d kbit/s\n" +"Protocol version: %d.%d\n" +"Security method: %s\n" +msgstr "" + +msgid "VNC connection info" +msgstr "" + +msgid "VNC Viewer: Connection Options" +msgstr "" + +msgid "Encoding and Color Level:" +msgstr "" + +msgid "Inputs:" +msgstr "" + +msgid "Misc:" +msgstr "" + +msgid "Auto select" +msgstr "" + +msgid "Full (all available colors)" +msgstr "" + +msgid "Medium (256 colors)" +msgstr "" + +msgid "Low (64 colors)" +msgstr "" + +msgid "Very low (8 colors)" +msgstr "" + +msgid "Custom compression level:" +msgstr "" + +msgid "level (1=fast, 9=best)" +msgstr "" + +msgid "Allow JPEG compression:" +msgstr "" + +msgid "quality (1=poor, 9=best)" +msgstr "" + +msgid "View only (ignore mouse & keyboard)" +msgstr "" + +msgid "Accept clipboard from server" +msgstr "" + +msgid "Send clipboard to server" +msgstr "" + +msgid "Send primary selection & cut buffer as clipboard" +msgstr "" + +msgid "Shared (don't disconnect other viewers)" +msgstr "" + +msgid "Full-screen mode" +msgstr "" + +msgid "Render cursor locally" +msgstr "" + +msgid "Show dot when no cursor" +msgstr "" + +msgid "OK" +msgstr "" + +msgid "Cancel" +msgstr "" + +msgid "Username:" +msgstr "" + +msgid "Password:" +msgstr "" + +msgid "VNC Viewer: Connection Details" +msgstr "" + +msgid "VNC server:" +msgstr "" + +msgid "About..." +msgstr "" + +#, c-format +msgid "" +"TightVNC viewer for X version 4.0 - built %s\n" +"Copyright (C) 2002-2004 RealVNC Ltd.\n" +"Copyright (C) 2000-2004 Constantin Kaplinsky\n" +"Copyright (C) 2004-2005 Peter Astrand, Cendio AB\n" +"See http://www.tightvnc.com for information on TightVNC." +msgstr "" diff --git a/unix/tx/Makefile.in b/unix/tx/Makefile.in new file mode 100644 index 00000000..89c30b17 --- /dev/null +++ b/unix/tx/Makefile.in @@ -0,0 +1,17 @@ + +SRCS = TXWindow.cxx TXScrollbar.cxx TXViewport.cxx TXImage.cxx TXMenu.cxx + +OBJS = $(SRCS:.cxx=.o) + +DIR_CPPFLAGS = -I$(top_srcdir) @X_CFLAGS@ # X_CFLAGS are really CPPFLAGS + +library = libtx.a + +all:: $(library) + +$(library): $(OBJS) + rm -f $(library) + $(AR) $(library) $(OBJS) + $(RANLIB) $(library) + +# followed by boilerplate.mk diff --git a/unix/tx/TXButton.h b/unix/tx/TXButton.h new file mode 100644 index 00000000..b7472797 --- /dev/null +++ b/unix/tx/TXButton.h @@ -0,0 +1,124 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXButton.h +// +// A TXButton is a clickable button with some text in it. The button must be +// big enough to contain the text - if not then it will be resized +// appropriately. +// + +#ifndef __TXBUTTON_H__ +#define __TXBUTTON_H__ + +#include "TXWindow.h" +#include + +// TXButtonCallback's buttonActivate() method is called when a button is +// activated. +class TXButton; +class TXButtonCallback { +public: + virtual void buttonActivate(TXButton* button)=0; +}; + + +class TXButton : public TXWindow, public TXEventHandler { +public: + + TXButton(Display* dpy_, const char* text_, TXButtonCallback* cb_=0, + TXWindow* parent_=0, int w=1, int h=1) + : TXWindow(dpy_, w, h, parent_), cb(cb_), down(false), + disabled_(false) + { + setEventHandler(this); + setText(text_); + gc = XCreateGC(dpy, win(), 0, 0); + XSetFont(dpy, gc, defaultFont); + addEventMask(ExposureMask | ButtonPressMask | ButtonReleaseMask); + } + + virtual ~TXButton() { + XFreeGC(dpy, gc); + } + + // setText() changes the text in the button. + void setText(const char* text_) { + text.buf = rfb::strDup(text_); + int textWidth = XTextWidth(defaultFS, text.buf, strlen(text.buf)); + int textHeight = (defaultFS->ascent + defaultFS->descent); + int newWidth = __rfbmax(width(), textWidth + xPad*2 + bevel*2); + int newHeight = __rfbmax(height(), textHeight + yPad*2 + bevel*2); + if (width() < newWidth || height() < newHeight) { + resize(newWidth, newHeight); + } + } + + // disabled() sets or queries the disabled state of the checkbox. A disabled + // checkbox cannot be changed via the user interface. + void disabled(bool b) { disabled_ = b; paint(); } + bool disabled() { return disabled_; } + +private: + + void paint() { + int tw = XTextWidth(defaultFS, text.buf, strlen(text.buf)); + int startx = (width() - tw) / 2; + int starty = (height() + defaultFS->ascent - defaultFS->descent) / 2; + if (down || disabled_) { + drawBevel(gc, 0, 0, width(), height(), bevel, defaultBg, darkBg,lightBg); + startx++; starty++; + } else { + drawBevel(gc, 0, 0, width(), height(), bevel, defaultBg, lightBg,darkBg); + } + + XSetForeground(dpy, gc, disabled_ ? disabledFg : defaultFg); + XDrawString(dpy, win(), gc, startx, starty, text.buf, strlen(text.buf)); + } + + virtual void handleEvent(TXWindow* w, XEvent* ev) { + switch (ev->type) { + case Expose: + paint(); + break; + case ButtonPress: + if (!disabled_) { + down = true; + paint(); + } + break; + case ButtonRelease: + if (!down) break; + down = false; + paint(); + if (ev->xbutton.x >= 0 && ev->xbutton.x < width() && + ev->xbutton.y >= 0 && ev->xbutton.y < height()) { + if (cb) cb->buttonActivate(this); + } + break; + } + } + + GC gc; + rfb::CharArray text; + TXButtonCallback* cb; + bool down; + bool disabled_; +}; + +#endif diff --git a/unix/tx/TXCheckbox.h b/unix/tx/TXCheckbox.h new file mode 100644 index 00000000..0880b38c --- /dev/null +++ b/unix/tx/TXCheckbox.h @@ -0,0 +1,142 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXCheckbox.h +// +// A TXCheckbox has a box which may be "checked" with some text next to it. +// The checkbox window must be big enough to contain the text - if not then it +// will be resized appropriately. +// +// There are two styles of checkbox: the normal style which uses a tick in a +// square box, and the radio style which uses a dot inside a circle. The +// default behaviour when clicking on the checkbox is to toggle it on or off, +// but this behaviour can be changed by the callback object. In particular to +// get radiobutton behaviour, the callback must ensure that only one of a set +// of radiobuttons is selected. +// + +#ifndef __TXCHECKBOX_H__ +#define __TXCHECKBOX_H__ + +#include "TXWindow.h" +#include + +// TXCheckboxCallback's checkboxSelect() method is called when the state of a +// checkbox changes. +class TXCheckbox; +class TXCheckboxCallback { +public: + virtual void checkboxSelect(TXCheckbox* checkbox)=0; +}; + + +class TXCheckbox : public TXWindow, public TXEventHandler { +public: + TXCheckbox(Display* dpy_, const char* text_, TXCheckboxCallback* cb_, + bool radio_=false, TXWindow* parent_=0, int w=1, int h=1) + : TXWindow(dpy_, w, h, parent_), cb(cb_), text(0), + boxSize(radio_ ? 12 : 13), boxPad(4), + checked_(false), disabled_(false), radio(radio_) + { + setEventHandler(this); + setText(text_); + gc = XCreateGC(dpy, win(), 0, 0); + XSetFont(dpy, gc, defaultFont); + addEventMask(ExposureMask| ButtonPressMask | ButtonReleaseMask); + } + + virtual ~TXCheckbox() { + XFreeGC(dpy, gc); + if (text) free(text); + } + + // setText() changes the text in the checkbox. + void setText(const char* text_) { + if (text) free(text); + text = strdup((char*)text_); + int textWidth = XTextWidth(defaultFS, text, strlen(text)); + int textHeight = (defaultFS->ascent + defaultFS->descent); + int newWidth = __rfbmax(width(), textWidth + xPad*2 + boxPad*2 + boxSize); + int newHeight = __rfbmax(height(), textHeight + yPad*2); + if (width() < newWidth || height() < newHeight) { + resize(newWidth, newHeight); + } + } + + // checked() sets or queries the state of the checkbox + void checked(bool b) { checked_ = b; paint(); } + bool checked() { return checked_; } + + // disabled() sets or queries the disabled state of the checkbox. A disabled + // checkbox cannot be changed via the user interface. + void disabled(bool b) { disabled_ = b; paint(); } + bool disabled() { return disabled_; } + +private: + void paint() { + if (disabled_) + drawBevel(gc, xPad + boxPad, (height() - boxSize) / 2, boxSize, boxSize, + bevel, disabledBg, darkBg, lightBg, radio); + else + drawBevel(gc, xPad + boxPad, (height() - boxSize) / 2, boxSize, boxSize, + bevel, enabledBg, darkBg, lightBg, radio); + XSetBackground(dpy, gc, disabled_ ? disabledBg : enabledBg); + XSetForeground(dpy, gc, disabled_ ? disabledFg : defaultFg); + if (checked_) { + Pixmap icon = radio ? dot : tick; + int iconSize = radio ? dotSize : tickSize; + XCopyPlane(dpy, icon, win(), gc, 0, 0, iconSize, iconSize, + xPad + boxPad + (boxSize - iconSize) / 2, + (height() - iconSize) / 2, 1); + } + XDrawString(dpy, win(), gc, xPad + boxSize + boxPad*2, + (height() + defaultFS->ascent - defaultFS->descent) / 2, + text, strlen(text)); + } + + virtual void handleEvent(TXWindow* w, XEvent* ev) { + switch (ev->type) { + case Expose: + paint(); + break; + case ButtonPress: + break; + case ButtonRelease: + if (ev->xbutton.x >= 0 && ev->xbutton.x < width() && + ev->xbutton.y >= 0 && ev->xbutton.y < height()) { + if (!disabled_) { + checked_ = !checked_; + if (cb) cb->checkboxSelect(this); + paint(); + } + } + break; + } + } + + TXCheckboxCallback* cb; + GC gc; + char* text; + int boxSize; + int boxPad; + bool checked_; + bool disabled_; + bool radio; +}; + +#endif diff --git a/unix/tx/TXDialog.h b/unix/tx/TXDialog.h new file mode 100644 index 00000000..c8d601c3 --- /dev/null +++ b/unix/tx/TXDialog.h @@ -0,0 +1,101 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXDialog.h +// +// A TXDialog is a pop-up dialog window. The dialog can be made visible by +// calling its show() method. Dialogs can be modal or non-modal. For a modal +// dialog box, the show() method only returns when the dialog box has been +// dismissed. For a non-modal dialog box, the show() method returns +// immediately. +// + +#ifndef __TXDIALOG_H__ +#define __TXDIALOG_H__ + +#include "TXWindow.h" +#include + +// XXX Lynx/OS 2.3: protos for bzero(), select() +#ifdef Lynx +#include +#endif + +class TXDialog : public TXWindow, public TXDeleteWindowCallback { +public: + TXDialog(Display* dpy, int width, int height, const char* name, + bool modal_=false) + : TXWindow(dpy, width, height), done(false), ok(false), modal(modal_) + { + toplevel(name, this); + resize(width, height); + } + + virtual ~TXDialog() {} + + // show() makes the dialog visible. For a modal dialog box, this processes X + // events until the done flag has been set, after which it returns the value + // of the ok flag. For a non-modal dialog box it always returns true + // immediately. + bool show() { + ok = false; + done = false; + initDialog(); + raise(); + map(); + if (modal) { + while (true) { + TXWindow::handleXEvents(dpy); + if (done) { + return ok; + } + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(ConnectionNumber(dpy), &rfds); + int n = select(FD_SETSIZE, &rfds, 0, 0, 0); + if (n < 0) throw rdr::SystemException("select",errno); + } + } + return true; + } + + // initDialog() can be overridden in a derived class. Typically it is used + // to make sure that checkboxes have the right state, etc. + virtual void initDialog() {} + + // resize() is overidden here to re-center the dialog + void resize(int w, int h) { + TXWindow::resize(w,h); + int dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy)); + int dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy)); + setUSPosition((dpyWidth - width() - 10) / 2, (dpyHeight - height() - 30) / 2); + } + +protected: + virtual void deleteWindow(TXWindow* w) { + ok = false; + done = true; + unmap(); + } + + bool done; + bool ok; + bool modal; +}; + +#endif diff --git a/unix/tx/TXEntry.h b/unix/tx/TXEntry.h new file mode 100644 index 00000000..1785a5f5 --- /dev/null +++ b/unix/tx/TXEntry.h @@ -0,0 +1,191 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXEntry.h +// +// A TXEntry allows you to enter a single line of text in a window. The entry +// must be tall enough to contain a line of text - if not then it will be +// resized appropriately. If the passwd argument to the constructor is true, +// then the text in the entry will be replaced by asterisks on the screen. +// + +#ifndef __TXENTRY_H__ +#define __TXENTRY_H__ + +#include "TXWindow.h" +#include + +#ifndef XK_ISO_Left_Tab +#define XK_ISO_Left_Tab 0xFE20 +#endif +#ifndef XK_KP_Delete +#define XK_KP_Delete 0xFF9F +#endif + +// TXEntryCallback's entryCallback() method is called when one of three special +// key presses have happened: Enter/Return, forward tab, or backward tab. +class TXEntry; +class TXEntryCallback { +public: + enum Detail { ENTER, NEXT_FOCUS, PREV_FOCUS }; + virtual void entryCallback(TXEntry* entry, Detail detail, Time time)=0; +}; + + +class TXEntry : public TXWindow, public TXEventHandler { +public: + + TXEntry(Display* dpy_, TXEntryCallback* cb_=0, + TXWindow* parent_=0, bool passwd_=false, int w=1, int h=1) + : TXWindow(dpy_, w, h, parent_), cb(cb_), + passwd(passwd_), disabled_(false), gotFocus(false) + { + setEventHandler(this); + gc = XCreateGC(dpy, win(), 0, 0); + addEventMask(ExposureMask | KeyPressMask | FocusChangeMask + | ButtonPressMask); + text[0] = 0; + int textHeight = (defaultFS->ascent + defaultFS->descent); + int newHeight = __rfbmax(height(), textHeight + yPad*2 + bevel*2); + if (height() < newHeight) { + resize(width(), newHeight); + } + } + + virtual ~TXEntry() { + XFreeGC(dpy, gc); + // overwrite memory used to store password - not critical, but can avoid + // accidental exposure of a password in uninitialised memory. + if (passwd) + memset(text, 0, maxLen); + } + + // getText() gets the text in the entry. + const char* getText() { return text; } + + // setText() sets the text in the entry. + void setText(const char* text_) { + strncpy(text, text_, maxLen-1); + text[maxLen-1] = 0; + paint(); + } + + // disabled() sets or queries the disabled state of the entry. A disabled + // entry cannot have text entered into it. + void disabled(bool b) { disabled_ = b; paint(); } + bool disabled() { return disabled_; } + +private: + void paint() { + if (disabled_) + drawBevel(gc, 0, 0, width(), height(), bevel, disabledBg,darkBg,lightBg); + else + drawBevel(gc, 0, 0, width(), height(), bevel, enabledBg, darkBg,lightBg); + char* str = text; + char stars[maxLen]; + if (passwd) { + int i; + for (i = 0; i < (int)strlen(text); i++) stars[i] = '*'; + stars[i] = 0; + str = stars; + } + int tw = XTextWidth(defaultFS, str, strlen(str)); + int startx = bevel + xPad; + if (startx + tw > width() - 2*bevel) { + startx = width() - 2*bevel - tw; + } + XDrawString(dpy, win(), defaultGC, startx, + (height() + defaultFS->ascent - defaultFS->descent) / 2, + str, strlen(str)); + if (!disabled_ && gotFocus) + XDrawLine(dpy, win(), defaultGC, startx+tw, + (height() - defaultFS->ascent - defaultFS->descent) / 2, + startx+tw, + (height() + defaultFS->ascent + defaultFS->descent) / 2); + } + + virtual void handleEvent(TXWindow* w, XEvent* ev) { + switch (ev->type) { + case Expose: + paint(); + break; + + case FocusIn: + gotFocus = true; + paint(); + break; + + case FocusOut: + gotFocus = false; + paint(); + break; + + case ButtonPress: + if (!disabled_) + XSetInputFocus(dpy, win(), RevertToParent, ev->xbutton.time); + break; + + case KeyPress: + { + if (disabled_ || !gotFocus) break; + KeySym keysym; + XComposeStatus compose; + char buf[10]; + int count = XLookupString(&ev->xkey, buf, 10, &keysym, &compose); + if (count >= 1 && buf[0] >= ' ' && buf[0] <= '~') { + if (strlen(text) + count >= maxLen) { + XBell(dpy, 0); + } else { + strncat(text, buf, count); + paint(); + } + } else if (keysym == XK_BackSpace || keysym == XK_Delete || + keysym == XK_KP_Delete) { + if (strlen(text) > 0) { + text[strlen(text)-1] = 0; + paint(); + } + } else if (keysym == XK_Return || keysym == XK_KP_Enter || + keysym == XK_Linefeed) { + if (cb) cb->entryCallback(this, TXEntryCallback::ENTER, + ev->xkey.time); + } else if ((keysym == XK_Tab || keysym == XK_KP_Tab) + && !(ev->xkey.state & ShiftMask)) + { + if (cb) cb->entryCallback(this, TXEntryCallback::NEXT_FOCUS, + ev->xkey.time); + } else if (((keysym == XK_Tab || keysym == XK_KP_Tab) + && (ev->xkey.state & ShiftMask)) + || keysym == XK_ISO_Left_Tab) + { + if (cb) cb->entryCallback(this, TXEntryCallback::PREV_FOCUS, + ev->xkey.time); + } + } + } + } + GC gc; + enum { maxLen = 256 }; + char text[maxLen]; + TXEntryCallback* cb; + bool passwd; + bool disabled_; + bool gotFocus; +}; + +#endif diff --git a/unix/tx/TXImage.cxx b/unix/tx/TXImage.cxx new file mode 100644 index 00000000..5fa68288 --- /dev/null +++ b/unix/tx/TXImage.cxx @@ -0,0 +1,353 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXImage.cxx +// + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "TXWindow.h" +#include "TXImage.h" + +using namespace rfb; + +static rfb::LogWriter vlog("TXImage"); + +TXImage::TXImage(Display* d, int width, int height, Visual* vis_, int depth_) + : xim(0), dpy(d), vis(vis_), depth(depth_), tig(0), cube(0) +{ +#ifdef HAVE_MITSHM + shminfo = 0; +#endif + width_ = width; + height_ = height; + for (int i = 0; i < 256; i++) + colourMap[i].r = colourMap[i].g = colourMap[i].b = 0; + + if (!vis) + vis = DefaultVisual(dpy,DefaultScreen(dpy)); + if (!depth) + depth = DefaultDepth(dpy,DefaultScreen(dpy)); + + createXImage(); + getNativePixelFormat(vis, depth); + colourmap = this; + format.bpp = 0; // just make it different to any valid format, so that... + setPF(nativePF); // ...setPF() always works +} + +TXImage::~TXImage() +{ + if (data != (rdr::U8*)xim->data) delete [] data; + destroyXImage(); + delete tig; + delete cube; +} + +void TXImage::resize(int w, int h) +{ + if (w == width() && h == height()) return; + + int oldStrideBytes = getStride() * (format.bpp/8); + int rowsToCopy = __rfbmin(h, height()); + int bytesPerRow = __rfbmin(w, width()) * (format.bpp/8); + rdr::U8* oldData = 0; + bool allocData = false; + + if (data != (rdr::U8*)xim->data) { + oldData = (rdr::U8*)data; + allocData = true; + } else { + oldData = new rdr::U8[xim->bytes_per_line * height()]; + memcpy(oldData, xim->data, xim->bytes_per_line * height()); + } + + destroyXImage(); + width_ = w; + height_ = h; + createXImage(); + + if (allocData) + data = new rdr::U8[width() * height() * (format.bpp/8)]; + else + data = (rdr::U8*)xim->data; + + int newStrideBytes = getStride() * (format.bpp/8); + for (int i = 0; i < rowsToCopy; i++) + memcpy((rdr::U8*)data + newStrideBytes * i, oldData + oldStrideBytes * i, + bytesPerRow); + delete [] oldData; +} + +void TXImage::setPF(const PixelFormat& newPF) +{ + if (newPF.equal(format)) return; + format = newPF; + + if (data != (rdr::U8*)xim->data) delete [] data; + delete tig; + tig = 0; + + if (format.equal(nativePF) && format.trueColour) { + data = (rdr::U8*)xim->data; + } else { + data = new rdr::U8[width() * height() * (format.bpp/8)]; + tig = new TransImageGetter(); + tig->init(this, nativePF, 0, cube); + } +} + +int TXImage::getStride() const +{ + if (data == (rdr::U8*)xim->data) + return xim->bytes_per_line / (xim->bits_per_pixel / 8); + else + return width(); +} + +void TXImage::put(Window win, GC gc, const rfb::Rect& r) +{ + if (r.is_empty()) return; + int x = r.tl.x; + int y = r.tl.y; + int w = r.width(); + int h = r.height(); + if (data != (rdr::U8*)xim->data) { + rdr::U8* ximDataStart = ((rdr::U8*)xim->data + y * xim->bytes_per_line + + x * (xim->bits_per_pixel / 8)); + tig->getImage(ximDataStart, r, + xim->bytes_per_line / (xim->bits_per_pixel / 8)); + } +#ifdef HAVE_MITSHM + if (usingShm()) { + XShmPutImage(dpy, win, gc, xim, x, y, x, y, w, h, False); + return; + } +#endif + XPutImage(dpy, win, gc, xim, x, y, x, y, w, h); +} + +void TXImage::setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs) +{ + for (int i = 0; i < nColours; i++) { + colourMap[firstColour+i].r = rgbs[i*3]; + colourMap[firstColour+i].g = rgbs[i*3+1]; + colourMap[firstColour+i].b = rgbs[i*3+2]; + } +} + +void TXImage::updateColourMap() +{ + tig->setColourMapEntries(0, 0, 0); +} + +void TXImage::lookup(int index, int* r, int* g, int* b) +{ + *r = colourMap[index].r; + *g = colourMap[index].g; + *b = colourMap[index].b; +} + +#ifdef HAVE_MITSHM +static bool caughtError = false; + +static int XShmAttachErrorHandler(Display *dpy, XErrorEvent *error) +{ + caughtError = true; + return 0; +} + +class TXImageCleanup { +public: + std::list images; + ~TXImageCleanup() { + while (!images.empty()) + delete images.front(); + } +}; + +static TXImageCleanup imageCleanup; +#endif + +void TXImage::createXImage() +{ +#ifdef HAVE_MITSHM + int major, minor; + Bool pixmaps; + + if (XShmQueryVersion(dpy, &major, &minor, &pixmaps)) { + shminfo = new XShmSegmentInfo; + + xim = XShmCreateImage(dpy, vis, depth, ZPixmap, + 0, shminfo, width(), height()); + + if (xim) { + shminfo->shmid = shmget(IPC_PRIVATE, + xim->bytes_per_line * xim->height, + IPC_CREAT|0777); + + if (shminfo->shmid != -1) { + shminfo->shmaddr = xim->data = (char*)shmat(shminfo->shmid, 0, 0); + + if (shminfo->shmaddr != (char *)-1) { + + shminfo->readOnly = False; + + XErrorHandler oldHdlr = XSetErrorHandler(XShmAttachErrorHandler); + XShmAttach(dpy, shminfo); + XSync(dpy, False); + XSetErrorHandler(oldHdlr); + + if (!caughtError) { + vlog.debug("Using shared memory XImage"); + imageCleanup.images.push_back(this); + return; + } + + shmdt(shminfo->shmaddr); + } else { + vlog.error("shmat failed"); + perror("shmat"); + } + + shmctl(shminfo->shmid, IPC_RMID, 0); + } else { + vlog.error("shmget failed"); + perror("shmget"); + } + + XDestroyImage(xim); + xim = 0; + } else { + vlog.error("XShmCreateImage failed"); + } + + delete shminfo; + shminfo = 0; + } +#endif + + xim = XCreateImage(dpy, vis, depth, ZPixmap, + 0, 0, width(), height(), BitmapPad(dpy), 0); + + xim->data = (char*)malloc(xim->bytes_per_line * xim->height); + if (!xim->data) { + vlog.error("malloc failed"); + exit(1); + } +} + +void TXImage::destroyXImage() +{ +#ifdef HAVE_MITSHM + if (shminfo) { + vlog.debug("Freeing shared memory XImage"); + shmdt(shminfo->shmaddr); + shmctl(shminfo->shmid, IPC_RMID, 0); + delete shminfo; + shminfo = 0; + imageCleanup.images.remove(this); + } +#endif + // XDestroyImage() will free(xim->data) if appropriate + if (xim) XDestroyImage(xim); + xim = 0; +} + + +static bool supportedBPP(int bpp) { + return (bpp == 8 || bpp == 16 || bpp == 32); +} + +static int depth2bpp(Display* dpy, int depth) +{ + int nformats; + XPixmapFormatValues* format = XListPixmapFormats(dpy, &nformats); + + int i; + for (i = 0; i < nformats; i++) + if (format[i].depth == depth) break; + + if (i == nformats || !supportedBPP(format[i].bits_per_pixel)) + throw rfb::Exception("Error: couldn't find suitable pixmap format"); + + int bpp = format[i].bits_per_pixel; + XFree(format); + return bpp; +} + +void TXImage::getNativePixelFormat(Visual* vis, int depth) +{ + cube = 0; + nativePF.depth = depth; + nativePF.bpp = depth2bpp(dpy, depth); + nativePF.bigEndian = (ImageByteOrder(dpy) == MSBFirst); + nativePF.trueColour = (vis->c_class == TrueColor); + + vlog.info("Using default colormap and visual, %sdepth %d.", + (vis->c_class == TrueColor) ? "TrueColor, " : + ((vis->c_class == PseudoColor) ? "PseudoColor, " : ""), + depth); + + if (nativePF.trueColour) { + + nativePF.redShift = ffs(vis->red_mask) - 1; + nativePF.greenShift = ffs(vis->green_mask) - 1; + nativePF.blueShift = ffs(vis->blue_mask) - 1; + nativePF.redMax = vis->red_mask >> nativePF.redShift; + nativePF.greenMax = vis->green_mask >> nativePF.greenShift; + nativePF.blueMax = vis->blue_mask >> nativePF.blueShift; + + } else { + + XColor xc[256]; + cube = new rfb::ColourCube(6,6,6); + int r; + for (r = 0; r < cube->nRed; r++) { + for (int g = 0; g < cube->nGreen; g++) { + for (int b = 0; b < cube->nBlue; b++) { + int i = (r * cube->nGreen + g) * cube->nBlue + b; + xc[i].red = r * 65535 / (cube->nRed-1); + xc[i].green = g * 65535 / (cube->nGreen-1); + xc[i].blue = b * 65535 / (cube->nBlue-1); + } + } + } + + TXWindow::getColours(dpy, xc, cube->size()); + + for (r = 0; r < cube->nRed; r++) { + for (int g = 0; g < cube->nGreen; g++) { + for (int b = 0; b < cube->nBlue; b++) { + int i = (r * cube->nGreen + g) * cube->nBlue + b; + cube->set(r, g, b, xc[i].pixel); + } + } + } + } +} diff --git a/unix/tx/TXImage.h b/unix/tx/TXImage.h new file mode 100644 index 00000000..055bd22d --- /dev/null +++ b/unix/tx/TXImage.h @@ -0,0 +1,97 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXImage.h +// +// A TXImage represents a rectangular off-screen image in any RFB pixel format. +// By default it will use the "native" pixel format for the screen, which will +// be an 8-bit colourmap unless the X display is TrueColor. The pixel format +// can be changed via the setPF() method. The pixel data is accessible via the +// data member inherited from FullFramePixelBuffer, or can be set via the +// fillRect(), imageRect(), copyRect() and maskRect() methods, also inherited +// from PixelBuffer. A rectangle of the image can be drawn into an X Window +// via the put() method. If using a colourmap, the setColourMapEntries() and +// updateColourMap() methods must be called to set up the colourmap as +// appropriate. + + +#ifndef __TXIMAGE_H__ +#define __TXIMAGE_H__ + +#include +#include +#include +#include +#ifdef HAVE_MITSHM +#include +#endif + +namespace rfb { class TransImageGetter; } + +class TXImage : public rfb::FullFramePixelBuffer, public rfb::ColourMap { +public: + TXImage(Display* dpy, int width, int height, Visual* vis=0, int depth=0); + ~TXImage(); + + // resize() resizes the image, preserving the image data where possible. + void resize(int w, int h); + + // put causes the given rectangle to be drawn onto the given window. + void put(Window win, GC gc, const rfb::Rect& r); + + // setColourMapEntries() changes some of the entries in the colourmap. + // However these settings won't take effect until updateColourMap() is + // called. This is because recalculating the internal translation table can + // be expensive. + void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs); + void updateColourMap(); + +#ifdef HAVE_MITSHM + bool usingShm() { return shminfo; } +#else + bool usingShm() { return 0; } +#endif + + // PixelBuffer methods + // width(), height(), getPF() etc are inherited from PixelBuffer + virtual void setPF(const rfb::PixelFormat& pf); + virtual int getStride() const; + +private: + + // ColourMap method + virtual void lookup(int index, int* r, int* g, int* b); + + void createXImage(); + void destroyXImage(); + void getNativePixelFormat(Visual* vis, int depth); + + XImage* xim; + Display* dpy; + Visual* vis; + int depth; +#ifdef HAVE_MITSHM + XShmSegmentInfo* shminfo; +#endif + rfb::TransImageGetter* tig; + rfb::Colour colourMap[256]; + rfb::PixelFormat nativePF; + rfb::ColourCube* cube; +}; + +#endif diff --git a/unix/tx/TXLabel.h b/unix/tx/TXLabel.h new file mode 100644 index 00000000..3d5200d6 --- /dev/null +++ b/unix/tx/TXLabel.h @@ -0,0 +1,126 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXLabel.h +// +// An TXLabel allows you to put up multiline text in a window with various +// alignments. The label must be big enough to contain the text - if not then +// it will be resized appropriately. +// + +#ifndef __TXLABEL_H__ +#define __TXLABEL_H__ + +#include +#include "TXWindow.h" +#include + +class TXLabel : public TXWindow, public TXEventHandler { +public: + enum HAlign { left, centre, right }; + enum VAlign { top, middle, bottom }; + + TXLabel(Display* dpy_, const char* text_, TXWindow* parent_=0, + int w=1, int h=1, HAlign ha=centre, VAlign va=middle) + : TXWindow(dpy_, w, h, parent_), lineSpacing(2), lines(0), + halign(ha), valign(va) + { + setEventHandler(this); + setText(text_); + addEventMask(ExposureMask); + } + + // setText() changes the text in the label. + void setText(const char* text_) { + text.buf = rfb::strDup(text_); + lines = 0; + int lineStart = 0; + int textWidth = 0; + int i = -1; + do { + i++; + if (text.buf[i] == '\n' || text.buf[i] == 0) { + int tw = XTextWidth(defaultFS, &text.buf[lineStart], i-lineStart); + if (tw > textWidth) textWidth = tw; + lineStart = i+1; + lines++; + } + } while (text.buf[i] != 0); + int textHeight = ((defaultFS->ascent + defaultFS->descent + lineSpacing) + * lines); + int newWidth = __rfbmax(width(), textWidth + xPad*2); + int newHeight = __rfbmax(height(), textHeight + yPad*2); + if (width() < newWidth || height() < newHeight) { + resize(newWidth, newHeight); + } + invalidate(); + } + +private: + int xOffset(int textWidth) { + switch (halign) { + case left: return xPad; + case right: return width() - xPad - textWidth; + default: return (width() - textWidth) / 2; + } + } + + int yOffset(int lineNum) { + int textHeight = ((defaultFS->ascent + defaultFS->descent + lineSpacing) + * lines); + int lineOffset = ((defaultFS->ascent + defaultFS->descent + lineSpacing) + * lineNum + defaultFS->ascent); + switch (valign) { + case top: return yPad + lineOffset; + case bottom: return height() - yPad - textHeight + lineOffset; + default: return (height() - textHeight) / 2 + lineOffset; + } + } + + void paint() { + int lineNum = 0; + int lineStart = 0; + int i = -1; + do { + i++; + if (text.buf[i] == '\n' || text.buf[i] == 0) { + int tw = XTextWidth(defaultFS, &text.buf[lineStart], i-lineStart); + XDrawString(dpy, win(), defaultGC, xOffset(tw), yOffset(lineNum), + &text.buf[lineStart], i-lineStart); + lineStart = i+1; + lineNum++; + } + } while (text.buf[i] != 0); + } + + virtual void handleEvent(TXWindow* w, XEvent* ev) { + switch (ev->type) { + case Expose: + paint(); + break; + } + } + + int lineSpacing; + rfb::CharArray text; + int lines; + HAlign halign; + VAlign valign; +}; + +#endif diff --git a/unix/tx/TXMenu.cxx b/unix/tx/TXMenu.cxx new file mode 100644 index 00000000..92712f55 --- /dev/null +++ b/unix/tx/TXMenu.cxx @@ -0,0 +1,186 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXMenu.cxx +// + +#include "TXMenu.h" +#include +#include +#include +#include +#include +#include + +TXMenu::TXMenu(Display* dpy_, TXMenuCallback* cb_, int w, int h, + TXWindow* parent_) + : TXWindow(dpy_, w, h, parent_), cb(cb_), nEntries(0), + highlight(-1) +{ + setEventHandler(this); + gc = XCreateGC(dpy, win(), 0, 0); + addEventMask(ExposureMask | ButtonPressMask | ButtonReleaseMask | + PointerMotionMask | EnterWindowMask | LeaveWindowMask); +} + +TXMenu::~TXMenu() +{ + XFreeGC(dpy, gc); + for (int i = 0; i < nEntries; i++) + delete [] text[i]; +} + +inline int TXMenu::entryHeight(int i) +{ + if (text[i]) + return defaultFS->ascent + defaultFS->descent + bevel*2 + yPad*2; + else + return yPad*2 + 1; +} + +void TXMenu::addEntry(const char* text_, long id_) +{ + assert(nEntries < maxEntries); + text[nEntries] = rfb::strDup(text_); + checked[nEntries] = false; + id[nEntries++] = id_; + int tw = 0; + if (text_) + tw = XTextWidth(defaultFS, text_, strlen(text_)); + int newWidth = width(); + if (tw + bevel*2 + xPad*5 + tickSize > width()) + newWidth = tw + bevel*2 + xPad*5 + tickSize; + int newHeight = 0; + for (int i = 0; i < nEntries; i++) + newHeight += entryHeight(i); + resize(newWidth, newHeight); +} + +void TXMenu::check(long id_, bool checked_) +{ + for (int i = 0; i < nEntries; i++) { + if (id[i] == id_) { + checked[i] = checked_; + break; + } + } +} + +void TXMenu::paint() +{ + int y = 0; + for (int i = 0; i < nEntries; i++) { + if (text[i]) { + if (i == highlight) + drawBevel(gc, 0, y, width(), entryHeight(i), bevel, + defaultBg, darkBg, lightBg); + else + XClearArea(dpy, win(), 0, y, width(), entryHeight(i), false); + if (checked[i]) + XCopyPlane(dpy, tick, win(), defaultGC, 0, 0, tickSize, tickSize, + bevel + xPad, + y + bevel + yPad + defaultFS->ascent - tickSize, 1); + + XDrawImageString(dpy, win(), defaultGC, bevel + xPad*2 + tickSize, + y + bevel + yPad + defaultFS->ascent, + text[i], strlen(text[i])); + } else { + XDrawLine(dpy, win(), defaultGC, bevel + xPad, y + entryHeight(i) / 2, + width() - bevel - xPad, y + entryHeight(i) / 2); + } + y += entryHeight(i); + } +} + +void TXMenu::handleEvent(TXWindow* w, XEvent* ev) +{ + switch (ev->type) { + case Expose: + paint(); + break; + + case ButtonRelease: + { + int y = ev->xmotion.y; + int entryY = 0; + for (int i = 0; i < nEntries; i++) { + if (y >= entryY && y <= entryY + entryHeight(i)) { + if (cb && text[i]) + cb->menuSelect(id[i], this); + break; + } + entryY += entryHeight(i); + } + highlight = -1; + paint(); + break; + } + + case ButtonPress: + case MotionNotify: + { + int y = ev->xmotion.y; + int entryY = 0; + for (int i = 0; i < nEntries; i++) { + if (y >= entryY && y <= entryY + entryHeight(i)) { + if (highlight != i) { + highlight = i; + paint(); + } + break; + } + entryY += entryHeight(i); + } + break; + } + + case KeyPress: + { + KeySym ks; + char str[256]; + XLookupString(&ev->xkey, str, 256, &ks, NULL); + if (ks == XK_Escape) { + highlight = -1; + unmap(); + } else if (ks == XK_Down || ks == XK_Up) { + if (nEntries < 1) break; + if (highlight < 0) + highlight = (ks == XK_Down ? nEntries-1 : 0); + int start = highlight; + int inc = (ks == XK_Down ? 1 : nEntries-1); + do { + highlight = (highlight + inc) % nEntries; + } while (highlight != start && !text[highlight]); + paint(); + } else if (ks == XK_space || ks == XK_KP_Space || + ks == XK_Return || ks == XK_KP_Enter) { + if (cb && highlight >= 0 && text[highlight]) + cb->menuSelect(id[highlight], this); + highlight = -1; + paint(); + } + break; + } + + case EnterNotify: + case LeaveNotify: + highlight = -1; + paint(); + break; + } +} diff --git a/unix/tx/TXMenu.h b/unix/tx/TXMenu.h new file mode 100644 index 00000000..d0245ee9 --- /dev/null +++ b/unix/tx/TXMenu.h @@ -0,0 +1,67 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXMenu.h +// +// A TXMenu consists of multiple entries which can be added one at a time. +// Each entry consists of some text, and has an associated integer identifier. +// A callback is made when a menu entry is selected. +// + +#ifndef __TXMENU_H__ +#define __TXMENU_H__ + +#include "TXWindow.h" + +// TXMenuCallback's menuSelect() method is called when a particular menu entry +// is selected. The id argument identifies the menu entry. +class TXMenu; +class TXMenuCallback { +public: + virtual void menuSelect(long id, TXMenu* menu)=0; +}; + +class TXMenu : public TXWindow, public TXEventHandler { +public: + TXMenu(Display* dpy_, TXMenuCallback* cb=0, int width=1, int height=1, + TXWindow* parent_=0); + virtual ~TXMenu(); + + // addEntry() adds an entry to the end of the menu with the given text and + // identifier. + void addEntry(const char* text, long id); + + // check() sets whether the given menu entry should have a tick next to it. + void check(long id, bool checked); + +private: + int entryHeight(int i); + virtual void handleEvent(TXWindow* w, XEvent* ev); + void paint(); + + GC gc; + TXMenuCallback* cb; + enum { maxEntries = 64 }; + char* text[maxEntries]; + long id[maxEntries]; + bool checked[maxEntries]; + int nEntries; + int highlight; +}; + +#endif diff --git a/unix/tx/TXMsgBox.h b/unix/tx/TXMsgBox.h new file mode 100644 index 00000000..ff84e6ae --- /dev/null +++ b/unix/tx/TXMsgBox.h @@ -0,0 +1,112 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXMsgBox.h +// +// A TXMsgBox is a specialised pop-up dialog window, designed to present +// the user with a small amount of textual information, and potentially to +// obtain their response. +// TXMsgBoxes are always modal, and may have an Ok button, Ok+Cancel buttons, +// or Yes+No buttons. +// The MsgBox helper function creates a TXMsgBox on the fly, runs it, and +// returns the result. +// + +#ifndef __TXMSGBOX_H__ +#define __TXMSGBOX_H__ + +#include "TXDialog.h" +#include "TXLabel.h" +#include "TXButton.h" + +enum TXMsgBoxFlags { + MB_OK = 0, + MB_OKCANCEL = 1, + MB_YESNO = 4, + MB_ICONERROR = 0x10, + MB_ICONQUESTION = 0x20, + MB_ICONWARNING = 0x30, + MB_ICONINFORMATION = 0x40, + MB_DEFBUTTON1 = 0, + MB_DEFBUTTON2 = 0x100 +}; + +class TXMsgBox : public TXDialog, public TXButtonCallback { +public: + TXMsgBox(Display* dpy, const char* text, unsigned int flags, const char* title=0) + : TXDialog(dpy, 1, 1, "Message", true), + textLabel(dpy, "", this), + okButton(dpy, "OK", this, this, 60), + cancelButton(dpy, "Cancel", this, this, 60) + { + textLabel.xPad = 8; + textLabel.move(0, yPad*4); + textLabel.setText(text); + resize(textLabel.width(), + textLabel.height() + okButton.height() + yPad*12); + + switch (flags & 0x30) { + case MB_ICONERROR: + toplevel("Error", this); break; + case MB_ICONQUESTION: + toplevel("Question", this); break; + case MB_ICONWARNING: + toplevel("Warning", this); break; + case MB_ICONINFORMATION: + toplevel("Information", this); break; + default: + if (title) + toplevel(title, this); + break; + }; + + switch (flags & 0x7) { + default: + okButton.move((width() - okButton.width()) / 2, + height() - yPad*4 - okButton.height()); + cancelButton.unmap(); + break; + case MB_OKCANCEL: + case MB_YESNO: + + okButton.move(((width()/2) - okButton.width()) / 2, + height() - yPad*4 - okButton.height()); + cancelButton.move(((width()*3/2) - cancelButton.width()) / 2, + height() - yPad*4 - cancelButton.height()); + if ((flags & 0x7) == MB_YESNO) { + okButton.setText("Yes"); + cancelButton.setText("No"); + } + break; + }; + + setBorderWidth(1); + } + + virtual void buttonActivate(TXButton* b) { + ok = (b == &okButton); + done = true; + unmap(); + } + + TXLabel textLabel; + TXButton okButton; + TXButton cancelButton; +}; + +#endif diff --git a/unix/tx/TXScrollbar.cxx b/unix/tx/TXScrollbar.cxx new file mode 100644 index 00000000..47e124c3 --- /dev/null +++ b/unix/tx/TXScrollbar.cxx @@ -0,0 +1,119 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXScrollbar.cxx +// + +#include "TXScrollbar.h" +#include +#include + +TXScrollbar::TXScrollbar(Display* dpy_, int width, int height, bool vert, + TXScrollbarCallback* cb_, TXWindow* parent_) + : TXWindow(dpy_, width, height, parent_), cb(cb_), vertical(vert), + clickedInThumb(false) +{ + setEventHandler(this); + gc = XCreateGC(dpy, win(), 0, 0); + addEventMask(ExposureMask | ButtonPressMask | ButtonReleaseMask | + ButtonMotionMask); + setBg(scrollbarBg); + limit[0] = len[0] = limit[1] = len[1] = 1; + start[0] = start[1] = 0; +} + +TXScrollbar::~TXScrollbar() +{ + XFreeGC(dpy, gc); +} + +void TXScrollbar::set(int limit_, int start_, int len_, bool vert) +{ + assert(limit_ > 0 && len_ >= 0 && len_ <= limit_); + + if (start_ < 0) start_ = 0; + if (start_ > limit_ - len_) start_ = limit_ - len_; + + if (limit[vert] != limit_ || start[vert] != start_ || len[vert] != len_) { + limit[vert] = limit_; + start[vert] = start_; + len[vert] = len_; + paint(); + } +} + +void TXScrollbar::paint() +{ + int x = scaleToBarX(start[0]); + int y = scaleToBarY(start[1]); + int w = scaleToBarX(len[0]); + int h = scaleToBarY(len[1]); + if (y > 0) XClearArea(dpy, win(), 0, 0, 0, y, false); + if (x > 0) XClearArea(dpy, win(), 0, y, x, y+h, false); + XClearArea(dpy, win(), x+w, y, 0, y+h, false); + XClearArea(dpy, win(), 0, y+h, 0, 0, false); + drawBevel(gc, x, y, w, h, bevel, defaultBg, lightBg, darkBg); +} + +void TXScrollbar::handleEvent(TXWindow* w, XEvent* ev) +{ + switch (ev->type) { + case Expose: + paint(); + break; + + case ButtonPress: + { + xDown = ev->xbutton.x; + yDown = ev->xbutton.y; + xStart = start[0]; + yStart = start[1]; + bool clickedInThumbX = false; + if (xDown < scaleToBarX(start[0])) { + set(limit[0], start[0] - len[0], len[0], false); + } else if (xDown >= scaleToBarX(start[0]+len[0])) { + set(limit[0], start[0] + len[0], len[0], false); + } else { + clickedInThumbX = true; + } + bool clickedInThumbY = false; + if (yDown < scaleToBarY(start[1])) { + set(limit[1], start[1] - len[1], len[1], true); + } else if (yDown >= scaleToBarY(start[1]+len[1])) { + set(limit[1], start[1] + len[1], len[1], true); + } else { + clickedInThumbY = true; + } + clickedInThumb = clickedInThumbX && clickedInThumbY; + if (cb) cb->scrollbarPos(start[0], start[1], this); + } + break; + + case ButtonRelease: + case MotionNotify: + while (XCheckTypedWindowEvent(dpy, win(), MotionNotify, ev)); + if (clickedInThumb) { + int dx = ev->xmotion.x - xDown; + int dy = ev->xmotion.y - yDown; + set(limit[0], xStart + barToScaleX(dx), len[0], false); + set(limit[1], yStart + barToScaleY(dy), len[1], true); + if (cb) cb->scrollbarPos(start[0], start[1], this); + } + break; + } +} diff --git a/unix/tx/TXScrollbar.h b/unix/tx/TXScrollbar.h new file mode 100644 index 00000000..87fec3d8 --- /dev/null +++ b/unix/tx/TXScrollbar.h @@ -0,0 +1,82 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXScrollbar.h +// +// A TXScrollbar represents a range of values starting at start, of length len, +// between zero and limit. The vertical argument to the constructor says +// whether the scrollbar is horizontal or vertical. +// +// In fact it can represent a range in each dimension but usually one of the +// dimensions is fixed, according to the vertical flag (for a vertical +// scrollbar, the horizontal dimension is fixed, and vice-versa). +// +// The TXScrollbarCallback argument is an object which will be notified when +// the user has attempted to move the scrollbar. The x and y arguments to the +// scrollbarPos() method give the start values in the respective dimensions. +// They are guaranteed to be between 0 and limit-len. +// + +#ifndef __TXSCROLLBAR_H__ +#define __TXSCROLLBAR_H__ + +#include "TXWindow.h" + +class TXScrollbarCallback; + +class TXScrollbar : public TXWindow, public TXEventHandler { +public: + TXScrollbar(Display* dpy_, int width=1, int height=1, bool vertical=false, + TXScrollbarCallback* cb=0, TXWindow* parent_=0); + virtual ~TXScrollbar(); + + // set() sets the limit, start and length of the range represented by the + // scrollbar. The values of limit and len passed in must be valid + // (i.e. limit > 0 and 0 <= len <= limit). Values of start are clipped to + // the range 0 to limit-len. + void set(int limit, int start, int len) { set(limit, start, len, vertical); } + + // set() with an extra argument vert can be used to represent a range in both + // dimensions simultaneously. + void set(int limit, int start, int len, bool vert); + + virtual void handleEvent(TXWindow* w, XEvent* ev); + +private: + int scaleToBarX(int x) { return (x * width() + limit[0]/2) / limit[0]; } + int scaleToBarY(int y) { return (y * height() + limit[1]/2) / limit[1]; } + int barToScaleX(int x) { return (x * limit[0] + width()/2) / width(); } + int barToScaleY(int y) { return (y * limit[1] + height()/2) / height(); } + void paint(); + + GC gc; + TXScrollbarCallback* cb; + int limit[2]; + int start[2]; + int len[2]; + int xDown, yDown; + int xStart, yStart; + bool vertical; + bool clickedInThumb; +}; + +class TXScrollbarCallback { +public: + virtual void scrollbarPos(int x, int y, TXScrollbar* sb)=0; +}; +#endif diff --git a/unix/tx/TXViewport.cxx b/unix/tx/TXViewport.cxx new file mode 100644 index 00000000..abe51734 --- /dev/null +++ b/unix/tx/TXViewport.cxx @@ -0,0 +1,155 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXViewport.cxx +// + +#include "TXViewport.h" +#include + +TXViewport::TXViewport(Display* dpy_, int w, int h, TXWindow* parent_) + : TXWindow(dpy_, w, h, parent_), child(0), hScrollbar(0), + vScrollbar(0), scrollbarSize(15), xOff(0), yOff(0), bumpScrollTimer(this), + bumpScroll(false), needScrollbars(false), bumpScrollX(0), bumpScrollY(0) +{ + clipper = new TXWindow(dpy, width()-scrollbarSize, height()-scrollbarSize, + this); + clipper->setBg(black); + hScrollbar = new TXScrollbar(dpy, width()-scrollbarSize, scrollbarSize, + false, this, this); + vScrollbar = new TXScrollbar(dpy, scrollbarSize, height()-scrollbarSize, + true, this, this); +} + +TXViewport::~TXViewport() +{ + delete clipper; + delete hScrollbar; + delete vScrollbar; +} + +void TXViewport::setChild(TXWindow* child_) +{ + child = child_; + XReparentWindow(dpy, child->win(), clipper->win(), 0, 0); + xOff = yOff = 0; + child->map(); + resizeNotify(); +} + +bool TXViewport::setOffset(int x, int y) +{ + if (clipper->width() >= child->width()) { + x = (clipper->width() - child->width()) / 2; + } else { + if (x > 0) x = 0; + if (x + child->width() < clipper->width()) + x = clipper->width() - child->width(); + } + + if (clipper->height() >= child->height()) { + y = (clipper->height() - child->height()) / 2; + } else { + if (y > 0) y = 0; + if (y + child->height() < clipper->height()) + y = clipper->height() - child->height(); + } + + if (x != xOff || y != yOff) { + xOff = x; + yOff = y; + child->move(xOff, yOff); + return true; + } + + return false; +} + +void TXViewport::setBumpScroll(bool b) +{ + bumpScroll = b; + resizeNotify(); +} + +// Note: bumpScrollEvent() only works if the viewport is positioned at 0,0 and +// is the same width and height as the screen. +bool TXViewport::bumpScrollEvent(XMotionEvent* ev) +{ + if (!bumpScroll) return false; + int bumpScrollPixels = 20; + bumpScrollX = bumpScrollY = 0; + + if (ev->x_root == width()-1) bumpScrollX = -bumpScrollPixels; + else if (ev->x_root == 0) bumpScrollX = bumpScrollPixels; + if (ev->y_root == height()-1) bumpScrollY = -bumpScrollPixels; + else if (ev->y_root == 0) bumpScrollY = bumpScrollPixels; + + if (bumpScrollX || bumpScrollY) { + if (bumpScrollTimer.isStarted()) return true; + if (setOffset(xOff + bumpScrollX, yOff + bumpScrollY)) { + bumpScrollTimer.start(25); + return true; + } + } + + bumpScrollTimer.stop(); + return false; +} + +bool TXViewport::handleTimeout(rfb::Timer* timer) { + return setOffset(xOff + bumpScrollX, yOff + bumpScrollY); +} + +void TXViewport::resizeNotify() +{ + needScrollbars = (!bumpScroll && + (width() < child->width() || height() < child->height()) && + (width() > scrollbarSize && height() > scrollbarSize)); + if (needScrollbars) { + clipper->resize(width()-scrollbarSize, height()-scrollbarSize); + hScrollbar->map(); + vScrollbar->map(); + } else { + clipper->resize(width(), height()); + hScrollbar->unmap(); + vScrollbar->unmap(); + } + + setOffset(xOff, yOff); + + if (needScrollbars) { + hScrollbar->move(0, height()-scrollbarSize); + hScrollbar->resize(width()-scrollbarSize, scrollbarSize); + hScrollbar->set(child->width(), -xOff, width()-scrollbarSize); + vScrollbar->move(width()-scrollbarSize, 0); + vScrollbar->resize(scrollbarSize, height()-scrollbarSize); + vScrollbar->set(child->height(), -yOff, height()-scrollbarSize); + } +} + +void TXViewport::scrollbarPos(int x, int y, TXScrollbar* sb) +{ + if (sb == hScrollbar) { + x = -x; + y = yOff; + } else { + x = xOff; + y = -y; + } + setOffset(x, y); +} diff --git a/unix/tx/TXViewport.h b/unix/tx/TXViewport.h new file mode 100644 index 00000000..0c9857d2 --- /dev/null +++ b/unix/tx/TXViewport.h @@ -0,0 +1,77 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXViewport.h +// +// A TXViewport allows a large window to be viewed by adding scrollbars to the +// right and bottom if necessary. It also has a bump-scroll mode where there +// are no scrollbars, and scrolling is achieved by bumping up against the edge +// of the screen instead. Note that this only works when the viewport fills +// the entire screen. If the child window is smaller than the viewport, it is +// always positioned centrally in the viewport. + +#ifndef __TXVIEWPORT_H__ +#define __TXVIEWPORT_H__ + +#include +#include "TXWindow.h" +#include "TXScrollbar.h" + +class TXViewport : public TXWindow, public TXScrollbarCallback, + public rfb::Timer::Callback { +public: + TXViewport(Display* dpy_, int width, int height, TXWindow* parent_=0); + virtual ~TXViewport(); + + // setChild() sets the child window which is to be viewed in the viewport. + void setChild(TXWindow* child_); + + // setOffset() sets the position of the child in the viewport. Note that the + // offsets are negative. For example when the offset is (-100,-30), position + // (100,30) in the child window is at the top-left of the viewport. The + // offsets given are clipped to keep the child window filling the viewport + // (except where the child window is smaller than the viewport, in which case + // it is always positioned centrally in the viewport). It returns true if + // the child was repositioned. + bool setOffset(int x, int y); + + // setBumpScroll() puts the viewport in bump-scroll mode. + void setBumpScroll(bool b); + + // bumpScrollEvent() can be called with a MotionNotify event which may + // potentially be against the edge of the screen. It returns true if the + // event was used for bump-scrolling, false if it should be processed + // normally. + bool bumpScrollEvent(XMotionEvent* ev); + +private: + virtual void resizeNotify(); + virtual void scrollbarPos(int x, int y, TXScrollbar* sb); + virtual bool handleTimeout(rfb::Timer* timer); + TXWindow* clipper; + TXWindow* child; + TXScrollbar* hScrollbar; + TXScrollbar* vScrollbar; + const int scrollbarSize; + int xOff, yOff; + rfb::Timer bumpScrollTimer; + bool bumpScroll; + bool needScrollbars; + int bumpScrollX, bumpScrollY; +}; +#endif diff --git a/unix/tx/TXWindow.cxx b/unix/tx/TXWindow.cxx new file mode 100644 index 00000000..6d211beb --- /dev/null +++ b/unix/tx/TXWindow.cxx @@ -0,0 +1,486 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXWindow.cxx +// + +#include +#include "TXWindow.h" +#include +#include +#include +#include + +std::list windows; + +Atom wmProtocols, wmDeleteWindow, wmTakeFocus; +Atom xaTIMESTAMP, xaTARGETS, xaSELECTION_TIME, xaSELECTION_STRING; +Atom xaCLIPBOARD; +unsigned long TXWindow::black, TXWindow::white; +unsigned long TXWindow::defaultFg, TXWindow::defaultBg; +unsigned long TXWindow::lightBg, TXWindow::darkBg; +unsigned long TXWindow::disabledFg, TXWindow::disabledBg; +unsigned long TXWindow::enabledBg; +unsigned long TXWindow::scrollbarBg; +Colormap TXWindow::cmap = 0; +GC TXWindow::defaultGC = 0; +Font TXWindow::defaultFont = 0; +XFontStruct* TXWindow::defaultFS = 0; +Time TXWindow::cutBufferTime = 0; +Pixmap TXWindow::dot = 0, TXWindow::tick = 0; +const int TXWindow::dotSize = 4, TXWindow::tickSize = 8; +char* TXWindow::defaultWindowClass; + +void TXWindow::init(Display* dpy, const char* defaultWindowClass_) +{ + cmap = DefaultColormap(dpy,DefaultScreen(dpy)); + wmProtocols = XInternAtom(dpy, "WM_PROTOCOLS", False); + wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + wmTakeFocus = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + xaTIMESTAMP = XInternAtom(dpy, "TIMESTAMP", False); + xaTARGETS = XInternAtom(dpy, "TARGETS", False); + xaSELECTION_TIME = XInternAtom(dpy, "SELECTION_TIME", False); + xaSELECTION_STRING = XInternAtom(dpy, "SELECTION_STRING", False); + xaCLIPBOARD = XInternAtom(dpy, "CLIPBOARD", False); + XColor cols[6]; + cols[0].red = cols[0].green = cols[0].blue = 0x0000; + cols[1].red = cols[1].green = cols[1].blue = 0xbbbb; + cols[2].red = cols[2].green = cols[2].blue = 0xeeee; + cols[3].red = cols[3].green = cols[3].blue = 0x5555; + cols[4].red = cols[4].green = cols[4].blue = 0x8888; + cols[5].red = cols[5].green = cols[5].blue = 0xffff; + getColours(dpy, cols, 6); + black = defaultFg = cols[0].pixel; + defaultBg = disabledBg = cols[1].pixel; + lightBg = cols[2].pixel; + darkBg = disabledFg = cols[3].pixel; + scrollbarBg = cols[4].pixel; + white = enabledBg = cols[5].pixel; + defaultGC = XCreateGC(dpy, DefaultRootWindow(dpy), 0, 0); + defaultFS + = XLoadQueryFont(dpy, "-*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*"); + if (!defaultFS) { + defaultFS = XLoadQueryFont(dpy, "fixed"); + if (!defaultFS) { + fprintf(stderr,"Failed to load any font\n"); + exit(1); + } + } + defaultFont = defaultFS->fid; + XSetForeground(dpy, defaultGC, defaultFg); + XSetBackground(dpy, defaultGC, defaultBg); + XSetFont(dpy, defaultGC, defaultFont); + XSelectInput(dpy, DefaultRootWindow(dpy), PropertyChangeMask); + + static char dotBits[] = { 0x06, 0x0f, 0x0f, 0x06}; + dot = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), dotBits, + dotSize, dotSize); + static char tickBits[] = { 0x80, 0xc0, 0xe2, 0x76, 0x3e, 0x1c, 0x08, 0x00}; + tick = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), tickBits, + tickSize, tickSize); + defaultWindowClass = rfb::strDup(defaultWindowClass_); +} + +void TXWindow::handleXEvents(Display* dpy) +{ + while (XPending(dpy)) { + XEvent ev; + XNextEvent(dpy, &ev); + if (ev.type == MappingNotify) { + XRefreshKeyboardMapping(&ev.xmapping); + } else if (ev.type == PropertyNotify && + ev.xproperty.window == DefaultRootWindow(dpy) && + ev.xproperty.atom == XA_CUT_BUFFER0) { + cutBufferTime = ev.xproperty.time; + } else { + std::list::iterator i; + for (i = windows.begin(); i != windows.end(); i++) { + if ((*i)->win() == ev.xany.window) + (*i)->handleXEvent(&ev); + } + } + } +} + +void TXWindow::getColours(Display* dpy, XColor* cols, int nCols) +{ + bool* got = new bool[nCols]; + bool failed = false; + int i; + for (i = 0; i < nCols; i++) { + if (XAllocColor(dpy, cmap, &cols[i])) { + got[i] = true; + } else { + got[i] = false; + failed = true; + } + } + + if (!failed) { + delete [] got; + return; + } + + // AllocColor has failed. This is because the colormap is full. So the + // only thing we can do is use the "shared" pixels in the colormap. The + // code below is designed to work even when the colormap isn't full so is + // more complex than it needs to be in this case. However it would be + // useful one day to be able to restrict the number of colours allocated by + // an application so I'm leaving it in here. + + // For each pixel in the colormap, try to allocate exactly its RGB values. + // If this returns a different pixel then it must be a private or + // unallocated pixel, so we can't use it. If it returns us the same pixel + // again, it's almost certainly a shared colour, so we can use it (actually + // it is possible that it was an unallocated pixel which we've now + // allocated - by going through the pixels in reverse order we make this + // unlikely except for the lowest unallocated pixel - this works because of + // the way the X server allocates new pixels). + + int cmapSize = DisplayCells(dpy,DefaultScreen(dpy)); + + XColor* cm = new XColor[cmapSize]; + bool* shared = new bool[cmapSize]; + bool* usedAsNearest = new bool[cmapSize]; + + for (i = 0; i < cmapSize; i++) { + cm[i].pixel = i; + shared[i] = usedAsNearest[i] = false; + } + + XQueryColors(dpy, cmap, cm, cmapSize); + + for (i = cmapSize-1; i >= 0; i--) { + if (XAllocColor(dpy, cmap, &cm[i])) { + if (cm[i].pixel == (unsigned long)i) { + shared[i] = true; + } else { + XFreeColors(dpy, cmap, &cm[i].pixel, 1, 0); + } + } + } + + for (int j = 0; j < nCols; j++) { + unsigned long minDistance = ULONG_MAX; + unsigned long nearestPixel = 0; + if (!got[j]) { + for (i = 0; i < cmapSize; i++) { + if (shared[i]) { + unsigned long rd = (cm[i].red - cols[j].red)/2; + unsigned long gd = (cm[i].green - cols[j].green)/2; + unsigned long bd = (cm[i].blue - cols[j].blue)/2; + unsigned long distance = (rd*rd + gd*gd + bd*bd); + + if (distance < minDistance) { + minDistance = distance; + nearestPixel = i; + } + } + } + + cols[j].pixel = nearestPixel; + usedAsNearest[nearestPixel] = true; + } + } + + for (i = 0; i < cmapSize; i++) { + if (shared[i] && !usedAsNearest[i]) { + unsigned long p = i; + XFreeColors(dpy, cmap, &p, 1, 0); + } + } +} + +Window TXWindow::windowWithName(Display* dpy, Window top, const char* name) +{ + char* windowName; + if (XFetchName(dpy, top, &windowName)) { + if (strcmp(windowName, name) == 0) { + XFree(windowName); + return top; + } + XFree(windowName); + } + + Window* children; + Window dummy; + unsigned int nchildren; + if (!XQueryTree(dpy, top, &dummy, &dummy, &children,&nchildren) || !children) + return 0; + + for (int i = 0; i < (int)nchildren; i++) { + Window w = windowWithName(dpy, children[i], name); + if (w) { + XFree((char*)children); + return w; + } + } + XFree((char*)children); + return 0; +} + + +TXWindow::TXWindow(Display* dpy_, int w, int h, TXWindow* parent_, + int borderWidth) + : dpy(dpy_), xPad(3), yPad(3), bevel(2), parent(parent_), width_(w), + height_(h), eventHandler(0), dwc(0), eventMask(0), toplevel_(false) +{ + sizeHints.flags = 0; + XSetWindowAttributes attr; + attr.background_pixel = defaultBg; + attr.border_pixel = 0; + Window par = parent ? parent->win() : DefaultRootWindow(dpy); + win_ = XCreateWindow(dpy, par, 0, 0, width_, height_, borderWidth, + CopyFromParent, CopyFromParent, CopyFromParent, + CWBackPixel | CWBorderPixel, &attr); + if (parent) map(); + + windows.push_back(this); +} + +TXWindow::~TXWindow() +{ + windows.remove(this); + XDestroyWindow(dpy, win()); +} + +void TXWindow::toplevel(const char* name, TXDeleteWindowCallback* dwc_, + int argc, char** argv, const char* windowClass, + bool iconic) +{ + toplevel_ = true; + XWMHints wmHints; + wmHints.flags = InputHint|StateHint; + wmHints.input = True; + wmHints.initial_state = iconic ? IconicState : NormalState; + XClassHint classHint; + if (!windowClass) windowClass = defaultWindowClass; + classHint.res_name = (char*)name; + classHint.res_class = (char*)windowClass; + XSetWMProperties(dpy, win(), 0, 0, argv, argc, + &sizeHints, &wmHints, &classHint); + XStoreName(dpy, win(), name); + XSetIconName(dpy, win(), name); + Atom protocols[10]; + int nProtocols = 0; + protocols[nProtocols++] = wmTakeFocus; + dwc = dwc_; + if (dwc) + protocols[nProtocols++] = wmDeleteWindow; + XSetWMProtocols(dpy, win(), protocols, nProtocols); + addEventMask(StructureNotifyMask); +} + +void TXWindow::setMaxSize(int w, int h) +{ + sizeHints.flags |= PMaxSize; + sizeHints.max_width = w; + sizeHints.max_height = h; + XSetWMNormalHints(dpy, win(), &sizeHints); +} + +void TXWindow::setUSPosition(int x, int y) +{ + sizeHints.flags |= USPosition; + sizeHints.x = x; + sizeHints.y = y; + XSetWMNormalHints(dpy, win(), &sizeHints); + move(x, y); +} + +void TXWindow::setGeometry(const char* geom, int x, int y, int w, int h) +{ + char defGeom[256]; + sprintf(defGeom,"%dx%d+%d+%d",w,h,x,y); + XWMGeometry(dpy, DefaultScreen(dpy), strEmptyToNull((char*)geom), defGeom, + 0, &sizeHints, &x, &y, &w, &h, &sizeHints.win_gravity); + sizeHints.flags |= PWinGravity; + setUSPosition(x, y); + resize(w, h); +} + +TXEventHandler* TXWindow::setEventHandler(TXEventHandler* h) +{ + TXEventHandler* old = eventHandler; + eventHandler = h; + return old; +} + +void TXWindow::addEventMask(long mask) +{ + eventMask |= mask; + XSelectInput(dpy, win(), eventMask); +} + +void TXWindow::removeEventMask(long mask) +{ + eventMask &= ~mask; + XSelectInput(dpy, win(), eventMask); +} + +void TXWindow::unmap() +{ + XUnmapWindow(dpy, win()); + if (toplevel_) { + XUnmapEvent ue; + ue.type = UnmapNotify; + ue.display = dpy; + ue.event = DefaultRootWindow(dpy); + ue.window = win(); + ue.from_configure = False; + XSendEvent(dpy, DefaultRootWindow(dpy), False, + (SubstructureRedirectMask|SubstructureNotifyMask), + (XEvent*)&ue); + } +} + +void TXWindow::resize(int w, int h) +{ + //if (w == width_ && h == height_) return; + XResizeWindow(dpy, win(), w, h); + width_ = w; + height_ = h; + resizeNotify(); +} + +void TXWindow::setBorderWidth(int bw) +{ + XWindowChanges c; + c.border_width = bw; + XConfigureWindow(dpy, win(), CWBorderWidth, &c); +} + +void TXWindow::ownSelection(Atom selection, Time time) +{ + XSetSelectionOwner(dpy, selection, win(), time); + if (XGetSelectionOwner(dpy, selection) == win()) { + selectionOwner_[selection] = true; + selectionOwnTime[selection] = time; + } +} + +void TXWindow::handleXEvent(XEvent* ev) +{ + switch (ev->type) { + + case ClientMessage: + if (ev->xclient.message_type == wmProtocols) { + if ((Atom)ev->xclient.data.l[0] == wmDeleteWindow) { + if (dwc) dwc->deleteWindow(this); + } else if ((Atom)ev->xclient.data.l[0] == wmTakeFocus) { + takeFocus(ev->xclient.data.l[1]); + } + } + break; + + case ConfigureNotify: + if (ev->xconfigure.width != width_ || ev->xconfigure.height != height_) { + width_ = ev->xconfigure.width; + height_ = ev->xconfigure.height; + resizeNotify(); + } + break; + + case SelectionNotify: + if (ev->xselection.property != None) { + Atom type; + int format; + unsigned long nitems, after; + unsigned char *data; + XGetWindowProperty(dpy, win(), ev->xselection.property, 0, 16384, True, + AnyPropertyType, &type, &format, + &nitems, &after, &data); + if (type != None) { + selectionNotify(&ev->xselection, type, format, nitems, data); + XFree(data); + break; + } + } + selectionNotify(&ev->xselection, 0, 0, 0, 0); + break; + + case SelectionRequest: + { + XSelectionEvent se; + se.type = SelectionNotify; + se.display = ev->xselectionrequest.display; + se.requestor = ev->xselectionrequest.requestor; + se.selection = ev->xselectionrequest.selection; + se.time = ev->xselectionrequest.time; + se.target = ev->xselectionrequest.target; + if (ev->xselectionrequest.property == None) + ev->xselectionrequest.property = ev->xselectionrequest.target; + if (!selectionOwner_[se.selection]) { + se.property = None; + } else { + se.property = ev->xselectionrequest.property; + if (se.target == xaTARGETS) { + Atom targets[2]; + targets[0] = xaTIMESTAMP; + targets[1] = XA_STRING; + XChangeProperty(dpy, se.requestor, se.property, XA_ATOM, 32, + PropModeReplace, (unsigned char*)targets, 2); + } else if (se.target == xaTIMESTAMP) { + rdr::U32 t = selectionOwnTime[se.selection]; + XChangeProperty(dpy, se.requestor, se.property, XA_INTEGER, 32, + PropModeReplace, (unsigned char*)&t, 1); + } else if (se.target == XA_STRING) { + if (!selectionRequest(se.requestor, se.selection, se.property)) + se.property = None; + } + } + XSendEvent(dpy, se.requestor, False, 0, (XEvent*)&se); + break; + } + + case SelectionClear: + selectionOwner_[ev->xselectionclear.selection] = false; + break; + } + + if (eventHandler) eventHandler->handleEvent(this, ev); +} + +void TXWindow::drawBevel(GC gc, int x, int y, int w, int h, int b, + unsigned long middle, unsigned long tl, + unsigned long br, bool round) +{ + if (round) { + XGCValues gcv; + gcv.line_width = b; + XChangeGC(dpy, gc, GCLineWidth, &gcv); + XSetForeground(dpy, gc, middle); + XFillArc(dpy, win(), gc, x, y, w-b/2, h-b/2, 0, 360*64); + XSetForeground(dpy, gc, tl); + XDrawArc(dpy, win(), gc, x, y, w-b/2, h-b/2, 45*64, 180*64); + XSetForeground(dpy, gc, br); + XDrawArc(dpy, win(), gc, x, y, w-b/2, h-b/2, 225*64, 180*64); + } else { + XSetForeground(dpy, gc, middle); + if (w-2*b > 0 && h-2*b > 0) + XFillRectangle(dpy, win(), gc, x+b, y+b, w-2*b, h-2*b); + XSetForeground(dpy, gc, tl); + XFillRectangle(dpy, win(), gc, x, y, w, b); + XFillRectangle(dpy, win(), gc, x, y, b, h); + XSetForeground(dpy, gc, br); + for (int i = 0; i < b; i++) { + if (w-i > 0) XFillRectangle(dpy, win(), gc, x+i, y+h-1-i, w-i, 1); + if (h-1-i > 0) XFillRectangle(dpy, win(), gc, x+w-1-i, y+i+1, 1, h-1-i); + } + } +} diff --git a/unix/tx/TXWindow.h b/unix/tx/TXWindow.h new file mode 100644 index 00000000..5ada181b --- /dev/null +++ b/unix/tx/TXWindow.h @@ -0,0 +1,211 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// TXWindow.h +// +// A TXWindow is the base class for all tx windows (widgets). In addition it +// contains a number of static methods and members which are used throughout +// tx. +// +// Before calling any other tx methods, TXWindow::init() must be called with +// the X display to use. + +#ifndef __TXWINDOW_H__ +#define __TXWINDOW_H__ + +#include +#include +#include +#include +#include + + +// TXDeleteWindowCallback's deleteWindow() method is called when a top-level +// window is "deleted" (closed) by the user using the window manager. +class TXWindow; +class TXDeleteWindowCallback { +public: + virtual void deleteWindow(TXWindow* w) = 0; +}; + +// TXEventHandler is an interface implemented by classes wanting to handle X +// events on a window. Most derived classes of window are their own event +// handlers. +class TXEventHandler { +public: + virtual void handleEvent(TXWindow* w, XEvent* ev) = 0; +}; + +class TXWindow { +public: + + // Constructor - creates a window of the given size, with the default + // background (currently grey). It is mapped by default if it has a parent. + // If no parent is specified its parent is the root window and it will remain + // unmapped. + TXWindow(Display* dpy_, int width=1, int height=1, TXWindow* parent_=0, + int borderWidth=0); + virtual ~TXWindow(); + + // toplevel() declares that this is a top-level window. Various + // window-manager-related properties are set on the window. The given + // TXDeleteWindowCallback is notified when the window is "deleted" (cloesd) + // by the user. + void toplevel(const char* name, TXDeleteWindowCallback* dwc=0, + int argc=0, char** argv=0, const char* windowClass=0, + bool iconic=false); + + // setMaxSize() tells the window manager the maximum size to allow a + // top-level window. It has no effect on a non-top-level window. + void setMaxSize(int w, int h); + + // setUSPosition() tells the window manager the position which the "user" has + // asked for a top-level window. Most window managers ignore requests by a + // program for position, so you have to tell it that the "user" asked for the + // position. This has no effect on a non-top-level window. + void setUSPosition(int x, int y); + + void setGeometry(const char* geom, int x, int y, int w, int h); + + // setTransientFor() tells the window manager that this window is "owned" by + // the given window. The window manager can use this information as it sees + // fit. + void setTransientFor(Window w) { XSetTransientForHint(dpy, win(), w); } + + // setEventHandler() sets the TXEventHandler to handle X events for this + // window. It returns the previous event handler, so that handlers can chain + // themselves. + TXEventHandler* setEventHandler(TXEventHandler* h); + + // Accessor methods + Window win() { return win_; } + int width() { return width_; } + int height() { return height_; } + + // selectionOwner() returns true if this window owns the given selection. + bool selectionOwner(Atom selection) { return selectionOwner_[selection]; } + + // Wrappers around common Xlib calls + void addEventMask(long mask); + void removeEventMask(long mask); + void map() { XMapWindow(dpy, win()); } + void unmap(); + void setBg(unsigned long bg) { XSetWindowBackground(dpy, win(), bg); } + void move(int x, int y) { XMoveWindow(dpy, win(), x, y); } + void resize(int w, int h); + void raise() { XRaiseWindow(dpy, win()); } + void setBorderWidth(int bw); + void invalidate(int x=0, int y=0, int w=0, int h=0) { XClearArea(dpy, win(), x, y, w, h, True); } + + // ownSelection requests that the window owns the given selection from the + // given time (the time should be taken from an X event). + void ownSelection(Atom selection, Time time); + + + // drawBevel draws a rectangular or circular bevel filling the given + // rectangle, using the given colours for the middle, the top/left and the + // bottom/right. + void drawBevel(GC gc, int x, int y, int w, int h, int b, + unsigned long middle, unsigned long tl, unsigned long br, + bool round=false); + + // Methods to be overridden in a derived class + + // resizeNotify() is called whenever the window's dimensions may have + // changed. + virtual void resizeNotify() {} + + // takeFocus() is called when the window has received keyboard focus from the + // window manager. + virtual void takeFocus(Time time) {} + + // selectionNotify() is called when the selection owner has replied to a + // request for information about a selection from the selection owner. + virtual void selectionNotify(XSelectionEvent* ev, Atom type, int format, + int nitems, void* data) {} + + // selectionRequest() is called when this window is the selection owner and + // another X client has requested the selection. It should set the given + // property on the given window to the value of the given selection, + // returning true if successful, false otherwise. + virtual bool selectionRequest(Window requestor, + Atom selection, Atom property) { return false;} + + // Static methods + + // init() must be called before any other tx methods. + static void init(Display* dpy, const char* defaultWindowClass); + + // getColours() sets the pixel values in the cols array to the best available + // for the given rgb values, even in the case of a full colormap. + static void getColours(Display* dpy, XColor* cols, int nCols); + + // handleXEvents() should be called whenever there are events to handle on + // the connection to the X display. It process all available events, then + // returns when there are no more events to process. + static void handleXEvents(Display* dpy); + + // windowWithName() locates a window with a given name on a display. + static Window windowWithName(Display* dpy, Window top, const char* name); + + // strEmptyToNull() returns the string it's given but turns an empty string + // into null, which can be useful for passing rfb parameters to Xlib calls. + static char* strEmptyToNull(char* s) { return s && s[0] ? s : 0; } + + // The following are default values for various things. + static unsigned long black, white; + static unsigned long defaultFg, defaultBg, lightBg, darkBg; + static unsigned long disabledFg, disabledBg, enabledBg; + static unsigned long scrollbarBg; + static GC defaultGC; + static Colormap cmap; + static Font defaultFont; + static XFontStruct* defaultFS; + static Time cutBufferTime; + static Pixmap dot, tick; + static const int dotSize, tickSize; + static char* defaultWindowClass; + + Display* const dpy; + + int xPad, yPad, bevel; + +private: + + // handleXEvent() is called from handleXEvents() when an event for this + // window arrives. It does general event processing before calling on to the + // event handler. + void handleXEvent(XEvent* ev); + + TXWindow* parent; + Window win_; + int width_, height_; + TXEventHandler* eventHandler; + TXDeleteWindowCallback* dwc; + long eventMask; + XSizeHints sizeHints; + std::map selectionOwnTime; + std::map selectionOwner_; + bool toplevel_; +}; + +extern Atom wmProtocols, wmDeleteWindow, wmTakeFocus; +extern Atom xaTIMESTAMP, xaTARGETS, xaSELECTION_TIME, xaSELECTION_STRING; +extern Atom xaCLIPBOARD; + +#endif diff --git a/unix/vncconfig/Makefile.in b/unix/vncconfig/Makefile.in new file mode 100644 index 00000000..4891fcd8 --- /dev/null +++ b/unix/vncconfig/Makefile.in @@ -0,0 +1,23 @@ + +SRCS = vncExt.c vncconfig.cxx QueryConnectDialog.cxx + +OBJS = vncExt.o vncconfig.o QueryConnectDialog.o + +program = vncconfig + +DEP_LIBS = ../tx/libtx.a ../rfb/librfb.a ../network/libnetwork.a \ + ../rdr/librdr.a + +EXTRA_LIBS = @X_PRE_LIBS@ @X_LIBS@ -lX11 -lXext @X_EXTRA_LIBS@ + +DIR_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/tx @X_CFLAGS@ # X_CFLAGS are really CPPFLAGS + +all:: $(program) + +$(program): $(OBJS) buildtime.o $(DEP_LIBS) + rm -f $(program) + $(CXXLD) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJS) buildtime.o $(DEP_LIBS) $(LIBS) $(EXTRA_LIBS) + +buildtime.o: $(OBJS) $(DEP_LIBS) + +# followed by boilerplate.mk diff --git a/unix/vncconfig/QueryConnectDialog.cxx b/unix/vncconfig/QueryConnectDialog.cxx new file mode 100644 index 00000000..c1540513 --- /dev/null +++ b/unix/vncconfig/QueryConnectDialog.cxx @@ -0,0 +1,88 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include +#include "QueryConnectDialog.h" +#include "vncExt.h" + +QueryConnectDialog::QueryConnectDialog(Display* dpy, + const char* address_, + const char* user_, + int timeout_, + QueryResultCallback* cb) + : TXDialog(dpy, 300, 100, "VNC Server : Accept Connection?"), + addressLbl(dpy, "Host:",this), + address(dpy, address_, this), + userLbl(dpy, "User:", this), + user(dpy, user_, this), + timeoutLbl(dpy, "Seconds until automatic reject:", this), + timeout(dpy, "0000000000", this), + accept(dpy, "Accept", this, this, 60), + reject(dpy, "Reject", this, this, 60), + callback(cb), timeUntilReject(timeout_), timer(this) +{ + const int pad = 4; + int y=pad; + int lblWidth = __rfbmax(addressLbl.width(), userLbl.width()); + userLbl.move(pad+lblWidth-userLbl.width(), y); + user.move(pad+lblWidth, y); + addressLbl.move(pad+lblWidth-addressLbl.width(), y+=userLbl.height()); + address.move(pad+lblWidth, y); + timeoutLbl.move(pad, y+=addressLbl.height()); + timeout.move(pad+timeoutLbl.width(), y); + accept.move(pad, y+=addressLbl.height()); + int maxWidth = __rfbmax(user.width(), address.width()+pad+lblWidth); + maxWidth = __rfbmax(maxWidth, accept.width()*3); + maxWidth = __rfbmax(maxWidth, timeoutLbl.width()+timeout.width()+pad); + reject.move(maxWidth-reject.width(), y); + resize(maxWidth + pad, y+reject.height()+pad); + setBorderWidth(1); + refreshTimeout(); + timer.start(1000); +} + +void QueryConnectDialog::deleteWindow(TXWindow*) { + unmap(); + callback->queryRejected(); +} + +void QueryConnectDialog::buttonActivate(TXButton* b) { + unmap(); + if (b == &accept) + callback->queryApproved(); + else if (b == &reject) + callback->queryRejected(); +} + +bool QueryConnectDialog::handleTimeout(rfb::Timer* t) { + if (timeUntilReject-- == 0) { + unmap(); + callback->queryTimedOut(); + return false; + } else { + refreshTimeout(); + return true; + } +} + +void QueryConnectDialog::refreshTimeout() { + char buf[16]; + sprintf(buf, "%d", timeUntilReject); + timeout.setText(buf); +} diff --git a/unix/vncconfig/QueryConnectDialog.h b/unix/vncconfig/QueryConnectDialog.h new file mode 100644 index 00000000..f685dc34 --- /dev/null +++ b/unix/vncconfig/QueryConnectDialog.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef __QUERYCONNECTDIALOG_H__ +#define __QUERYCONNECTDIALOG_H__ + +#include +#include "TXLabel.h" +#include "TXButton.h" +#include "TXDialog.h" + +class QueryResultCallback { + public: + virtual ~QueryResultCallback() {} + virtual void queryApproved() = 0; + virtual void queryRejected() = 0; + virtual void queryTimedOut() { queryRejected(); }; +}; + +class QueryConnectDialog : public TXDialog, public TXEventHandler, + public TXButtonCallback, + public rfb::Timer::Callback +{ + public: + QueryConnectDialog(Display* dpy, const char* address_, + const char* user_, int timeout_, + QueryResultCallback* cb); + void handleEvent(TXWindow*, XEvent* ) { } + void deleteWindow(TXWindow*); + void buttonActivate(TXButton* b); + bool handleTimeout(rfb::Timer* t); + private: + void refreshTimeout(); + TXLabel addressLbl, address, userLbl, user, timeoutLbl, timeout; + TXButton accept, reject; + QueryResultCallback* callback; + int timeUntilReject; + rfb::Timer timer; +}; + +#endif diff --git a/unix/vncconfig/buildtime.c b/unix/vncconfig/buildtime.c new file mode 100644 index 00000000..3f4c3690 --- /dev/null +++ b/unix/vncconfig/buildtime.c @@ -0,0 +1,18 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +char buildtime[] = __DATE__ " " __TIME__; diff --git a/unix/vncconfig/vncExt.c b/unix/vncconfig/vncExt.c new file mode 100644 index 00000000..ff5532bf --- /dev/null +++ b/unix/vncconfig/vncExt.c @@ -0,0 +1,384 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#include + +#define NEED_REPLIES +#include +#include +#define _VNCEXT_PROTO_ +#include "vncExt.h" + +static Bool XVncExtClientCutTextNotifyWireToEvent(Display* dpy, XEvent* e, + xEvent* w); +static Bool XVncExtSelectionChangeNotifyWireToEvent(Display* dpy, XEvent* e, + xEvent* w); +static Bool XVncExtQueryConnectNotifyWireToEvent(Display* dpy, XEvent* e, + xEvent* w); + +static Bool extensionInited = False; +static XExtCodes* codes = 0; + +static Bool checkExtension(Display* dpy) +{ + if (!extensionInited) { + extensionInited = True; + codes = XInitExtension(dpy, VNCEXTNAME); + if (!codes) return False; + XESetWireToEvent(dpy, codes->first_event + VncExtClientCutTextNotify, + XVncExtClientCutTextNotifyWireToEvent); + XESetWireToEvent(dpy, codes->first_event + VncExtSelectionChangeNotify, + XVncExtSelectionChangeNotifyWireToEvent); + XESetWireToEvent(dpy, codes->first_event + VncExtQueryConnectNotify, + XVncExtQueryConnectNotifyWireToEvent); + } + return codes != 0; +} + +Bool XVncExtQueryExtension(Display* dpy, int* event_basep, int* error_basep) +{ + if (!checkExtension(dpy)) return False; + *event_basep = codes->first_event; + *error_basep = codes->first_error; + return True; +} + +Bool XVncExtSetParam(Display* dpy, const char* param) +{ + xVncExtSetParamReq* req; + xVncExtSetParamReply rep; + + int paramLen = strlen(param); + if (paramLen > 255) return False; + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtSetParam, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtSetParam; + req->length += (paramLen + 3) >> 2; + req->paramLen = paramLen; + Data(dpy, param, paramLen); + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + return rep.success; +} + +Bool XVncExtGetParam(Display* dpy, const char* param, char** value, int* len) +{ + xVncExtGetParamReq* req; + xVncExtGetParamReply rep; + + int paramLen = strlen(param); + *value = 0; + *len = 0; + if (paramLen > 255) return False; + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtGetParam, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtGetParam; + req->length += (paramLen + 3) >> 2; + req->paramLen = paramLen; + Data(dpy, param, paramLen); + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + if (rep.success) { + *len = rep.valueLen; + *value = (char*) Xmalloc (*len+1); + _XReadPad(dpy, *value, *len); + (*value)[*len] = 0; + } + UnlockDisplay(dpy); + SyncHandle(); + return rep.success; +} + +char* XVncExtGetParamDesc(Display* dpy, const char* param) +{ + xVncExtGetParamDescReq* req; + xVncExtGetParamDescReply rep; + char* desc = 0; + + int paramLen = strlen(param); + if (paramLen > 255) return False; + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtGetParamDesc, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtGetParamDesc; + req->length += (paramLen + 3) >> 2; + req->paramLen = paramLen; + Data(dpy, param, paramLen); + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + if (rep.success) { + desc = (char*)Xmalloc(rep.descLen+1); + _XReadPad(dpy, desc, rep.descLen); + desc[rep.descLen] = 0; + } + UnlockDisplay(dpy); + SyncHandle(); + return desc; +} + +char** XVncExtListParams(Display* dpy, int* nParams) +{ + xVncExtListParamsReq* req; + xVncExtListParamsReply rep; + char** list = 0; + char* ch; + int rlen, paramLen, i; + + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtListParams, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtListParams; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + if (rep.nParams) { + list = (char**)Xmalloc(rep.nParams * sizeof(char*)); + rlen = rep.length << 2; + ch = (char*)Xmalloc(rlen + 1); + if (!list || !ch) { + if (list) Xfree((char*)list); + if (ch) Xfree(ch); + _XEatData(dpy, rlen); + UnlockDisplay(dpy); + SyncHandle(); + return 0; + } + _XReadPad(dpy, ch, rlen); + paramLen = *ch++; + for (i = 0; i < rep.nParams; i++) { + list[i] = ch; + ch += paramLen; + paramLen = *ch; + *ch++ = 0; + } + } + *nParams = rep.nParams; + UnlockDisplay(dpy); + SyncHandle(); + return list; +} + +void XVncExtFreeParamList(char** list) +{ + if (list) { + Xfree(list[0]-1); + Xfree((char*)list); + } +} + +Bool XVncExtSetServerCutText(Display* dpy, const char* str, int len) +{ + xVncExtSetServerCutTextReq* req; + + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtSetServerCutText, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtSetServerCutText; + req->length += (len + 3) >> 2; + req->textLen = len; + Data(dpy, str, len); + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool XVncExtGetClientCutText(Display* dpy, char** str, int* len) +{ + xVncExtGetClientCutTextReq* req; + xVncExtGetClientCutTextReply rep; + + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtGetClientCutText, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtGetClientCutText; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + *len = rep.textLen; + *str = (char*) Xmalloc (*len+1); + _XReadPad(dpy, *str, *len); + (*str)[*len] = 0; + return True; +} + +Bool XVncExtSelectInput(Display* dpy, Window w, int mask) +{ + xVncExtSelectInputReq* req; + + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtSelectInput, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtSelectInput; + req->window = w; + req->mask = mask; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool XVncExtConnect(Display* dpy, char* hostAndPort) +{ + xVncExtConnectReq* req; + xVncExtConnectReply rep; + + int strLen = strlen(hostAndPort); + if (strLen > 255) return False; + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtConnect, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtConnect; + req->length += (strLen + 3) >> 2; + req->strLen = strLen; + Data(dpy, hostAndPort, strLen); + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + return rep.success; +} + +Bool XVncExtGetQueryConnect(Display* dpy, char** addr, char** user, + int* timeout, void** opaqueId) +{ + xVncExtGetQueryConnectReq* req; + xVncExtGetQueryConnectReply rep; + + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtGetQueryConnect, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtGetQueryConnect; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + + *addr = Xmalloc(rep.addrLen+1); + _XReadPad(dpy, *addr, rep.addrLen); + (*addr)[rep.addrLen] = 0; + *user = Xmalloc(rep.userLen+1); + _XReadPad(dpy, *user, rep.userLen); + (*user)[rep.userLen] = 0; + *timeout = rep.timeout; + *opaqueId = (void*)rep.opaqueId; + return True; +} + +Bool XVncExtApproveConnect(Display* dpy, void* opaqueId, int approve) +{ + xVncExtApproveConnectReq* req; + + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtApproveConnect, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtApproveConnect; + req->approve = approve; + req->opaqueId = (CARD32)opaqueId; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + + +static Bool XVncExtClientCutTextNotifyWireToEvent(Display* dpy, XEvent* e, + xEvent* w) +{ + XVncExtClientCutTextEvent* ev = (XVncExtClientCutTextEvent*)e; + xVncExtClientCutTextNotifyEvent* wire = (xVncExtClientCutTextNotifyEvent*)w; + ev->type = wire->type & 0x7f; + ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire); + ev->send_event = (wire->type & 0x80) != 0; + ev->display = dpy; + ev->window = wire->window; + ev->time = wire->time; + return True; +} + +static Bool XVncExtSelectionChangeNotifyWireToEvent(Display* dpy, XEvent* e, + xEvent* w) +{ + XVncExtSelectionChangeEvent* ev = (XVncExtSelectionChangeEvent*)e; + xVncExtSelectionChangeNotifyEvent* wire + = (xVncExtSelectionChangeNotifyEvent*)w; + ev->type = wire->type & 0x7f; + ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire); + ev->send_event = (wire->type & 0x80) != 0; + ev->display = dpy; + ev->window = wire->window; + ev->selection = wire->selection; + return True; +} + +static Bool XVncExtQueryConnectNotifyWireToEvent(Display* dpy, XEvent* e, + xEvent* w) +{ + XVncExtQueryConnectEvent* ev = (XVncExtQueryConnectEvent*)e; + xVncExtQueryConnectNotifyEvent* wire + = (xVncExtQueryConnectNotifyEvent*)w; + ev->type = wire->type & 0x7f; + ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire); + ev->send_event = (wire->type & 0x80) != 0; + ev->display = dpy; + ev->window = wire->window; + return True; +} diff --git a/unix/vncconfig/vncExt.h b/unix/vncconfig/vncExt.h new file mode 100644 index 00000000..f1502c41 --- /dev/null +++ b/unix/vncconfig/vncExt.h @@ -0,0 +1,343 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#ifndef _VNCEXT_H_ +#define _VNCEXT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define X_VncExtSetParam 0 +#define X_VncExtGetParam 1 +#define X_VncExtGetParamDesc 2 +#define X_VncExtListParams 3 +#define X_VncExtSetServerCutText 4 +#define X_VncExtGetClientCutText 5 +#define X_VncExtSelectInput 6 +#define X_VncExtConnect 7 +#define X_VncExtGetQueryConnect 8 +#define X_VncExtApproveConnect 9 + +#define VncExtClientCutTextNotify 0 +#define VncExtSelectionChangeNotify 1 +#define VncExtQueryConnectNotify 2 +#define VncExtClientCutTextMask (1 << VncExtClientCutTextNotify) +#define VncExtSelectionChangeMask (1 << VncExtSelectionChangeNotify) +#define VncExtQueryConnectMask (1 << VncExtQueryConnectNotify) + +#define VncExtNumberEvents 3 +#define VncExtNumberErrors 0 + +#ifndef _VNCEXT_SERVER_ + +Bool XVncExtQueryExtension(Display* dpy, int* event_basep, int* error_basep); +Bool XVncExtSetParam(Display* dpy, const char* param); +Bool XVncExtGetParam(Display* dpy, const char* param, char** value, int* len); +char* XVncExtGetParamDesc(Display* dpy, const char* param); +char** XVncExtListParams(Display* dpy, int* nParams); +void XVncExtFreeParamList(char** list); +Bool XVncExtSetServerCutText(Display* dpy, const char* str, int len); +Bool XVncExtGetClientCutText(Display* dpy, char** str, int* len); +Bool XVncExtSelectInput(Display* dpy, Window w, int mask); +Bool XVncExtConnect(Display* dpy, char* hostAndPort); +Bool XVncExtGetQueryConnect(Display* dpy, char** addr, + char** user, int* timeout, void** opaqueId); +Bool XVncExtApproveConnect(Display* dpy, void* opaqueId, int approve); + + +typedef struct { + int type; + unsigned long serial; + Bool send_event; + Display *display; + Window window; + Time time; +} XVncExtClientCutTextEvent; + +typedef struct { + int type; + unsigned long serial; + Bool send_event; + Display *display; + Window window; + Atom selection; +} XVncExtSelectionChangeEvent; + +typedef struct { + int type; + unsigned long serial; + Bool send_event; + Display *display; + Window window; +} XVncExtQueryConnectEvent; + +#endif + +#ifdef _VNCEXT_PROTO_ + +#define VNCEXTNAME "VNC-EXTENSION" + +typedef struct { + CARD8 reqType; /* always VncExtReqCode */ + CARD8 vncExtReqType; /* always VncExtSetParam */ + CARD16 length B16; + CARD8 paramLen; + CARD8 pad0; + CARD16 pad1 B16; +} xVncExtSetParamReq; +#define sz_xVncExtSetParamReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE success; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 pad0 B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xVncExtSetParamReply; +#define sz_xVncExtSetParamReply 32 + + +typedef struct { + CARD8 reqType; /* always VncExtReqCode */ + CARD8 vncExtReqType; /* always VncExtGetParam */ + CARD16 length B16; + CARD8 paramLen; + CARD8 pad0; + CARD16 pad1 B16; +} xVncExtGetParamReq; +#define sz_xVncExtGetParamReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE success; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 valueLen B16; + CARD16 pad0 B16; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xVncExtGetParamReply; +#define sz_xVncExtGetParamReply 32 + + +typedef struct { + CARD8 reqType; /* always VncExtReqCode */ + CARD8 vncExtReqType; /* always VncExtGetParamDesc */ + CARD16 length B16; + CARD8 paramLen; + CARD8 pad0; + CARD16 pad1 B16; +} xVncExtGetParamDescReq; +#define sz_xVncExtGetParamDescReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE success; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 descLen B16; + CARD16 pad0 B16; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xVncExtGetParamDescReply; +#define sz_xVncExtGetParamDescReply 32 + + +typedef struct { + CARD8 reqType; /* always VncExtReqCode */ + CARD8 vncExtReqType; /* always VncExtListParams */ + CARD16 length B16; +} xVncExtListParamsReq; +#define sz_xVncExtListParamsReq 4 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE pad0; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD16 nParams B16; + CARD16 pad1 B16; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; +} xVncExtListParamsReply; +#define sz_xVncExtListParamsReply 32 + + +typedef struct { + CARD8 reqType; /* always VncExtReqCode */ + CARD8 vncExtReqType; /* always VncExtSetServerCutText */ + CARD16 length B16; + CARD32 textLen B32; +} xVncExtSetServerCutTextReq; +#define sz_xVncExtSetServerCutTextReq 8 + + +typedef struct { + CARD8 reqType; /* always VncExtReqCode */ + CARD8 vncExtReqType; /* always VncExtGetClientCutText */ + CARD16 length B16; +} xVncExtGetClientCutTextReq; +#define sz_xVncExtGetClientCutTextReq 4 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE pad0; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 textLen B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xVncExtGetClientCutTextReply; +#define sz_xVncExtGetClientCutTextReply 32 + + +typedef struct { + CARD8 reqType; /* always VncExtReqCode */ + CARD8 vncExtReqType; /* always VncExtSelectInput */ + CARD16 length B16; + CARD32 window B32; + CARD32 mask B32; +} xVncExtSelectInputReq; +#define sz_xVncExtSelectInputReq 12 + + +typedef struct { + CARD8 reqType; /* always VncExtReqCode */ + CARD8 vncExtReqType; /* always VncExtConnect */ + CARD16 length B16; + CARD8 strLen; + CARD8 pad0; + CARD16 pad1 B16; +} xVncExtConnectReq; +#define sz_xVncExtConnectReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE success; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 pad0 B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xVncExtConnectReply; +#define sz_xVncExtConnectReply 32 + + +typedef struct { + CARD8 reqType; /* always VncExtReqCode */ + CARD8 vncExtReqType; /* always VncExtGetQueryConnect */ + CARD16 length B16; +} xVncExtGetQueryConnectReq; +#define sz_xVncExtGetQueryConnectReq 4 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE pad0; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 addrLen B32; + CARD32 userLen B32; + CARD32 timeout B32; + CARD32 opaqueId B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xVncExtGetQueryConnectReply; +#define sz_xVncExtGetQueryConnectReply 32 + +typedef struct { + CARD8 reqType; /* always VncExtReqCode */ + CARD8 vncExtReqType; /* always VncExtApproveConnect */ + CARD16 length B16; + CARD8 approve; + CARD8 pad0; + CARD16 pad1; + CARD32 opaqueId B32; +} xVncExtApproveConnectReq; +#define sz_xVncExtApproveConnectReq 12 + + + +typedef struct { + BYTE type; /* always eventBase + VncExtClientCutTextNotify */ + BYTE pad0; + CARD16 sequenceNumber B16; + CARD32 window B32; + CARD32 time B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xVncExtClientCutTextNotifyEvent; +#define sz_xVncExtClientCutTextNotifyEvent 32 + +typedef struct { + BYTE type; /* always eventBase + VncExtSelectionChangeNotify */ + BYTE pad0; + CARD16 sequenceNumber B16; + CARD32 window B32; + CARD32 selection B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xVncExtSelectionChangeNotifyEvent; +#define sz_xVncExtSelectionChangeNotifyEvent 32 + +typedef struct { + BYTE type; /* always eventBase + VncExtQueryConnectNotify */ + BYTE pad0; + CARD16 sequenceNumber B16; + CARD32 window B32; + CARD32 pad6 B32; + CARD32 pad1 B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xVncExtQueryConnectNotifyEvent; +#define sz_xVncExtQueryConnectNotifyEvent 32 + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/unix/vncconfig/vncconfig.cxx b/unix/vncconfig/vncconfig.cxx new file mode 100644 index 00000000..c901d193 --- /dev/null +++ b/unix/vncconfig/vncconfig.cxx @@ -0,0 +1,438 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// VNC server configuration utility +// + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "vncExt.h" +#include +#include +#include +#include +#include +#include "TXWindow.h" +#include "TXCheckbox.h" +#include "TXLabel.h" +#include "QueryConnectDialog.h" + +using namespace rfb; + +LogWriter vlog("vncconfig"); + +StringParameter displayname("display", "The X display", ""); +BoolParameter noWindow("nowin", "Don't display a window", 0); +BoolParameter iconic("iconic", "Start with window iconified", 0); +BoolParameter sendPrimary("SendPrimary", "Send the PRIMARY as well as the " + "CLIPBOARD selection", true); +IntParameter pollTime("poll", + "How often to poll for clipboard changes in ms", 0); + +inline const char* selectionName(Atom sel) { + if (sel == xaCLIPBOARD) return "CLIPBOARD"; + if (sel == XA_PRIMARY) return "PRIMARY"; + return "unknown"; +} + +#define ACCEPT_CUT_TEXT "AcceptCutText" +#define SEND_CUT_TEXT "SendCutText" + +char* programName = 0; +Display* dpy; +int vncExtEventBase, vncExtErrorBase; + +static bool getBoolParam(Display* dpy, const char* param) { + char* data; + int len; + if (XVncExtGetParam(dpy, param, &data, &len)) { + if (strcmp(data,"1") == 0) return true; + } + return false; +} + +class VncConfigWindow : public TXWindow, public TXEventHandler, + public TXDeleteWindowCallback, + public TXCheckboxCallback, + public rfb::Timer::Callback, + public QueryResultCallback { +public: + VncConfigWindow(Display* dpy) + : TXWindow(dpy, 300, 100), cutText(0), cutTextLen(0), + acceptClipboard(dpy, "Accept clipboard from viewers", this, false, this), + sendClipboard(dpy, "Send clipboard to viewers", this, false, this), + sendPrimaryCB(dpy, "Send primary selection to viewers", this,false,this), + pollTimer(this), + queryConnectDialog(0) + { + selection[0] = selection[1] = 0; + selectionLen[0] = selectionLen[1] = 0; + int y = yPad; + acceptClipboard.move(xPad, y); + acceptClipboard.checked(getBoolParam(dpy, ACCEPT_CUT_TEXT)); + y += acceptClipboard.height(); + sendClipboard.move(xPad, y); + sendClipboard.checked(getBoolParam(dpy, SEND_CUT_TEXT)); + y += sendClipboard.height(); + sendPrimaryCB.move(xPad, y); + sendPrimaryCB.checked(sendPrimary); + sendPrimaryCB.disabled(!sendClipboard.checked()); + y += sendPrimaryCB.height(); + setEventHandler(this); + toplevel("VNC config", this, 0, 0, 0, iconic); + XVncExtSelectInput(dpy, win(), + VncExtClientCutTextMask| + VncExtSelectionChangeMask| + VncExtQueryConnectMask); + XConvertSelection(dpy, XA_PRIMARY, XA_STRING, + XA_PRIMARY, win(), CurrentTime); + XConvertSelection(dpy, xaCLIPBOARD, XA_STRING, + xaCLIPBOARD, win(), CurrentTime); + if (pollTime != 0) + pollTimer.start(pollTime); + } + + // handleEvent(). If we get a ClientCutTextNotify event from Xvnc, set the + // primary and clipboard selections to the clientCutText. If we get a + // SelectionChangeNotify event from Xvnc, set the serverCutText to the value + // of the new selection. + + virtual void handleEvent(TXWindow* w, XEvent* ev) { + if (acceptClipboard.checked()) { + if (ev->type == vncExtEventBase + VncExtClientCutTextNotify) { + XVncExtClientCutTextEvent* cutEv = (XVncExtClientCutTextEvent*)ev; + if (cutText) + XFree(cutText); + cutText = 0; + if (XVncExtGetClientCutText(dpy, &cutText, &cutTextLen)) { + vlog.debug("Got client cut text: '%.*s%s'", + cutTextLen<9?cutTextLen:8, cutText, + cutTextLen<9?"":"..."); + XStoreBytes(dpy, cutText, cutTextLen); + ownSelection(XA_PRIMARY, cutEv->time); + ownSelection(xaCLIPBOARD, cutEv->time); + delete [] selection[0]; + delete [] selection[1]; + selection[0] = selection[1] = 0; + selectionLen[0] = selectionLen[1] = 0; + } + } + } + if (sendClipboard.checked()) { + if (ev->type == vncExtEventBase + VncExtSelectionChangeNotify) { + vlog.debug("selection change event"); + XVncExtSelectionChangeEvent* selEv = (XVncExtSelectionChangeEvent*)ev; + if (selEv->selection == xaCLIPBOARD || + (selEv->selection == XA_PRIMARY && sendPrimaryCB.checked())) { + if (!selectionOwner(selEv->selection)) + XConvertSelection(dpy, selEv->selection, XA_STRING, + selEv->selection, win(), CurrentTime); + } + } + } + if (ev->type == vncExtEventBase + VncExtQueryConnectNotify) { + vlog.debug("query connection event"); + if (queryConnectDialog) + delete queryConnectDialog; + queryConnectDialog = 0; + char* qcAddress; + char* qcUser; + int qcTimeout; + if (XVncExtGetQueryConnect(dpy, &qcAddress, &qcUser, + &qcTimeout, &queryConnectId)) { + if (qcTimeout) + queryConnectDialog = new QueryConnectDialog(dpy, qcAddress, + qcUser, qcTimeout, + this); + if (queryConnectDialog) + queryConnectDialog->map(); + XFree(qcAddress); + XFree(qcUser); + } + } + } + + + // selectionRequest() is called when we are the selection owner and another X + // client has requested the selection. We simply put the server's cut text + // into the requested property. TXWindow will handle the rest. + bool selectionRequest(Window requestor, Atom selection, Atom property) + { + if (cutText) + XChangeProperty(dpy, requestor, property, XA_STRING, 8, + PropModeReplace, (unsigned char*)cutText, + cutTextLen); + return cutText; + } + + // selectionNotify() is called when we have requested the selection from the + // selection owner. + void selectionNotify(XSelectionEvent* ev, Atom type, int format, + int nitems, void* data) + { + if (ev->requestor != win() || ev->target != XA_STRING) + return; + + if (data && format == 8) { + int i = (ev->selection == XA_PRIMARY ? 0 : 1); + if (selectionLen[i] == nitems && memcmp(selection[i], data, nitems) == 0) + return; + delete [] selection[i]; + selection[i] = new char[nitems]; + memcpy(selection[i], data, nitems); + selectionLen[i] = nitems; + if (cutTextLen == nitems && memcmp(cutText, data, nitems) == 0) { + vlog.debug("ignoring duplicate cut text"); + return; + } + if (cutText) + XFree(cutText); + cutText = (char*)malloc(nitems); // assuming XFree() same as free() + memcpy(cutText, data, nitems); + cutTextLen = nitems; + vlog.debug("sending %s selection as server cut text: '%.*s%s'", + selectionName(ev->selection),cutTextLen<9?cutTextLen:8, + cutText, cutTextLen<9?"":"..."); + XVncExtSetServerCutText(dpy, cutText, cutTextLen); + } + } + + // TXDeleteWindowCallback method + virtual void deleteWindow(TXWindow* w) { + exit(1); + } + + // TXCheckboxCallback method + virtual void checkboxSelect(TXCheckbox* checkbox) { + if (checkbox == &acceptClipboard) { + XVncExtSetParam(dpy, (acceptClipboard.checked() + ? ACCEPT_CUT_TEXT "=1" : ACCEPT_CUT_TEXT "=0")); + } else if (checkbox == &sendClipboard) { + XVncExtSetParam(dpy, (sendClipboard.checked() + ? SEND_CUT_TEXT "=1" : SEND_CUT_TEXT "=0")); + sendPrimaryCB.disabled(!sendClipboard.checked()); + } + } + + // rfb::Timer::Callback interface + virtual bool handleTimeout(rfb::Timer* timer) { + if (sendPrimaryCB.checked() && !selectionOwner(XA_PRIMARY)) + XConvertSelection(dpy, XA_PRIMARY, XA_STRING, + XA_PRIMARY, win(), CurrentTime); + if (!selectionOwner(xaCLIPBOARD)) + XConvertSelection(dpy, xaCLIPBOARD, XA_STRING, + xaCLIPBOARD, win(), CurrentTime); + return true; + } + + // QueryResultCallback interface + virtual void queryApproved() { + XVncExtApproveConnect(dpy, queryConnectId, 1); + } + virtual void queryRejected() { + XVncExtApproveConnect(dpy, queryConnectId, 0); + } + +private: + char* cutText; + int cutTextLen; + char* selection[2]; + int selectionLen[2]; + TXCheckbox acceptClipboard, sendClipboard, sendPrimaryCB; + rfb::Timer pollTimer; + + QueryConnectDialog* queryConnectDialog; + void* queryConnectId; +}; + +static void usage() +{ + fprintf(stderr,"usage: %s [parameters]\n", + programName); + fprintf(stderr," %s [parameters] -connect [:]\n", + programName); + fprintf(stderr," %s [parameters] -disconnect\n", programName); + fprintf(stderr," %s [parameters] [-set] = ...\n", + programName); + fprintf(stderr," %s [parameters] -list\n", programName); + fprintf(stderr," %s [parameters] -get \n", programName); + fprintf(stderr," %s [parameters] -desc \n",programName); + fprintf(stderr,"\n" + "Parameters can be turned on with - or off with -=0\n" + "Parameters which take a value can be specified as " + "- \n" + "Other valid forms are = -= " + "--=\n" + "Parameter names are case-insensitive. The parameters are:\n\n"); + Configuration::listParams(79, 14); + exit(1); +} + +void removeArgs(int* argc, char** argv, int first, int n) +{ + if (first + n > *argc) return; + for (int i = first + n; i < *argc; i++) + argv[i-n] = argv[i]; + *argc -= n; +} + +int main(int argc, char** argv) +{ + programName = argv[0]; + rfb::initStdIOLoggers(); + rfb::LogWriter::setLogParams("*:stderr:30"); + + // Process vncconfig's own parameters first, then we process the + // other arguments when we have the X display. + int i; + for (i = 1; i < argc; i++) { + if (Configuration::setParam(argv[i])) + continue; + + if (argv[i][0] == '-' && i+1 < argc && + Configuration::setParam(&argv[i][1], argv[i+1])) { + i++; + continue; + } + break; + } + + CharArray displaynameStr(displayname.getData()); + if (!(dpy = XOpenDisplay(displaynameStr.buf))) { + fprintf(stderr,"%s: unable to open display \"%s\"\n", + programName, XDisplayName(displaynameStr.buf)); + exit(1); + } + + if (!XVncExtQueryExtension(dpy, &vncExtEventBase, &vncExtErrorBase)) { + fprintf(stderr,"No VNC extension on display %s\n", + XDisplayName(displaynameStr.buf)); + exit(1); + } + + if (i < argc) { + for (; i < argc; i++) { + if (strcmp(argv[i], "-connect") == 0) { + i++; + if (i >= argc) usage(); + if (!XVncExtConnect(dpy, argv[i])) { + fprintf(stderr,"connecting to %s failed\n",argv[i]); + } + } else if (strcmp(argv[i], "-disconnect") == 0) { + if (!XVncExtConnect(dpy, "")) { + fprintf(stderr,"disconnecting all clients failed\n"); + } + } else if (strcmp(argv[i], "-get") == 0) { + i++; + if (i >= argc) usage(); + char* data; + int len; + if (XVncExtGetParam(dpy, argv[i], &data, &len)) { + printf("%.*s\n",len,data); + } else { + fprintf(stderr,"getting param %s failed\n",argv[i]); + } + XFree(data); + } else if (strcmp(argv[i], "-desc") == 0) { + i++; + if (i >= argc) usage(); + char* desc = XVncExtGetParamDesc(dpy, argv[i]); + if (desc) { + printf("%s\n",desc); + } else { + fprintf(stderr,"getting description for param %s failed\n",argv[i]); + } + XFree(desc); + } else if (strcmp(argv[i], "-list") == 0) { + int nParams; + char** list = XVncExtListParams(dpy, &nParams); + for (int i = 0; i < nParams; i++) { + printf("%s\n",list[i]); + } + XVncExtFreeParamList(list); + } else if (strcmp(argv[i], "-set") == 0) { + i++; + if (i >= argc) usage(); + if (!XVncExtSetParam(dpy, argv[i])) { + fprintf(stderr,"setting param %s failed\n",argv[i]); + } + } else if (XVncExtSetParam(dpy, argv[i])) { + fprintf(stderr,"set parameter %s\n",argv[i]); + } else { + usage(); + } + } + + return 0; + } + + try { + TXWindow::init(dpy,"Vncconfig"); + + VncConfigWindow w(dpy); + if (!noWindow) w.map(); + + while (true) { + struct timeval tv; + struct timeval* tvp = 0; + + // Process any incoming X events + TXWindow::handleXEvents(dpy); + + // Process expired timers and get the time until the next one + int timeoutMs = Timer::checkTimeouts(); + if (timeoutMs) { + tv.tv_sec = timeoutMs / 1000; + tv.tv_usec = (timeoutMs % 1000) * 1000; + tvp = &tv; + } + + // If there are X requests pending then poll, don't wait! + if (XPending(dpy)) { + tv.tv_usec = tv.tv_sec = 0; + tvp = &tv; + } + + // Wait for X events, VNC traffic, or the next timer expiry + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(ConnectionNumber(dpy), &rfds); + int n = select(FD_SETSIZE, &rfds, 0, 0, tvp); + if (n < 0) throw rdr::SystemException("select",errno); + } + + XCloseDisplay(dpy); + + } catch (rdr::Exception &e) { + vlog.error(e.str()); + } + + return 0; +} diff --git a/unix/vncconfig/vncconfig.man b/unix/vncconfig/vncconfig.man new file mode 100644 index 00000000..e24753da --- /dev/null +++ b/unix/vncconfig/vncconfig.man @@ -0,0 +1,128 @@ +.TH vncconfig 1 "17 Apr 2006" "TightVNC" "Virtual Network Computing" +.SH NAME +vncconfig \- configure and control a VNC server +.SH SYNOPSIS +.B vncconfig +.RI [ parameters ] +.br +.B vncconfig +.RI [ parameters ] +.B \-connect +.IR host [: port ] +.br +.B vncconfig +.RI [ parameters ] +.B \-disconnect +.br +.B vncconfig +.RI [ parameters ] +.RB [ -set ] +.IR Xvnc-param = value " ..." +.br +.B vncconfig +.RI [ parameters ] +.B \-list +.br +.B vncconfig +.RI [ parameters ] +\fB\-get\fP \fIXvnc-param\fP +.br +.B vncconfig +.RI [ parameters ] +\fB\-desc\fP \fIXvnc-param\fP +.SH DESCRIPTION +.B vncconfig +is used to configure and control a running instance of Xvnc, or any other X +server with the VNC extension. Note that it cannot be used to control VNC +servers prior to version 4. + +When run with no options, it runs as a kind of "helper" application for Xvnc. +Its main purpose when run in this mode is to support clipboard transfer to and +from the VNC viewer(s). Note that without a running instance of +\fBvncconfig\fP there will be no clipboard support. It puts up a window with +some checkboxes which can be used to disable clipboard transfers if required +(in the future there may be more functions available from this window). The +\fB-nowin\fP flag can be used if you always want clipboard support but don't +wish to clutter the desktop with this window - alternatively the \fB-iconic\fP +option can be used to make it iconified by default. + +When run in any other mode, \fBvncconfig\fP is a one-shot program used to +configure or control Xvnc as appropriate. It can be used to tell Xvnc to +connect or disconnect from listening viewers, and to set and retrieve Xvnc's +parameters. + +Note that the DISPLAY environment variable or the \fB\-display\fP option +must be set as appropriate to control Xvnc. If you run it on an ordinary X +server (or on a version 3 Xvnc) you will get an error message saying that there +is no VNC extension. + +.SH OPTIONS +.TP +.B \-connect \fIhost\fP[:\fIport\fP] +Tells an Xvnc server to make a "reverse" connection to a listening VNC viewer +(normally connections are made the other way round - the viewer connects to the +server). \fIhost\fP is the host where the listening viewer is running. If it's +not listening on the default port of 5500, you can specify \fIhost:port\fP +instead. + +.TP +.B \-disconnect +This causes Xvnc to disconnect from all viewers so that the VNC desktop is not +displayed anywhere. + +.TP +[\fB-set\fP] \fIXvnc-param\fP=\fIvalue\fP +Sets an Xvnc parameter to the given value. Note that some of Xvnc's parameters +are read only once at startup so that changing them in this way may not have +any effect. + +.TP +.B \-list +Lists all the parameters supported by Xvnc. + +.TP +.B \-get \fIXvnc-param\fP +Prints the current value of the given Xvnc parameter. + +.TP +.B \-desc \fIXvnc-param\fP +Prints a short description of the given Xvnc parameter. + +.SH PARAMETERS +.B vncconfig +also has parameters of its own which can be set on the command line. These +should not be confused with Xvnc's parameters which are manipulated with the +\fB-set\fP, \fB-get\fP, \fB-list\fP and \fB-desc\fP options. + +Parameters can be turned on with -\fIparam\fP or off with -\fIparam\fP=0. +Parameters which take a value can be specified as -\fIparam\fP \fIvalue\fP. +Other valid forms are \fIparam\fP\fB=\fP\fIvalue\fP -\fIparam\fP=\fIvalue\fP +--\fIparam\fP=\fIvalue\fP. Parameter names are case-insensitive. + +.TP +.B \-display \fIXdisplay\fP +Specifies the Xvnc server to control. + +.TP +.B \-nowin +When run as a "helper" app, don't put up a window. + +.TP +.B \-iconic +When run as a "helper" app, make the window iconified at startup. + +.SH SEE ALSO +.BR vncpasswd (1), +.BR vncviewer (1), +.BR vncserver (1), +.BR Xvnc (1) +.br +http://www.tightvnc.com + +.SH AUTHOR +Tristan Richardson, RealVNC Ltd. + +VNC was originally developed by the RealVNC team while at Olivetti +Research Ltd / AT&T Laboratories Cambridge. TightVNC additions was +implemented by Constantin Kaplinsky. Many other people participated in +development, testing and support. diff --git a/unix/vncinstall b/unix/vncinstall new file mode 100755 index 00000000..ad5dd838 --- /dev/null +++ b/unix/vncinstall @@ -0,0 +1,97 @@ +#!/bin/sh +# +# Copyright (C) 2002-2005 RealVNC Ltd. +# +# This 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. +# +# This software is distributed in the hope that 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 software; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. +# + +# +# vncinstall - copy the VNC programs to an installation directory. +# Also tries to install the manual pages somewhere sensible. +# + +if [ $# -lt 1 -o $# -gt 3 -o ! -d "$1" ]; then + echo "usage: $0 [] []" + echo "e.g. $0 /usr/local/bin" + exit 1 +fi + +dst=$1 +shift +if [ $# -gt 0 ]; then + mandst="$1/man1" + shift + if [ $# -gt 0 ]; then + moduledst=$1 + shift + else + moduledst=/usr/X11R6/lib/modules/extensions + fi +else + if [ "`basename $dst`" = bin ]; then + mandst="`dirname $dst`/man/man1" + if [ ! -d "$mandst" -a "$dst" = /usr/bin ]; then + mandst=/usr/share/man/man1 + fi + fi +fi + +if [ "$mandst" != "" ]; then + if [ ! -d "$mandst" -o ! -w "$mandst" ]; then + echo "Can't install manual pages to $mandst" + mandst="" + fi +fi + +for f in xc/programs/Xserver/Xvnc vncviewer/vncviewer vncpasswd/vncpasswd \ + vncconfig/vncconfig vncserver x0vncserver/x0vncserver; do + if [ ! -f $f ]; then + echo "Couldn't find $f" + else + if cmp -s $f $dst/`basename $f`; then + echo "`basename $f` hasn't changed" + else + echo "Copying $f to $dst" + cp -pf $f $dst + chmod 0555 $dst/`basename $f` + fi + + + if [ -f $f.man ]; then + if [ "$mandst" != "" -a -d "$mandst" ]; then + if cmp -s $f.man $mandst/`basename $f.1`; then + echo "`basename $f.man` hasn't changed" + else + echo "Copying $f.man to $mandst/`basename $f.1`" + cp -pf $f.man $mandst/`basename $f.1` + chmod 0444 $mandst/`basename $f.1` + fi + fi + fi + fi + +done + +vncModule=xc/programs/Xserver/vnc/module/vnc.so +if [ -f "$vncModule" -a -d "$moduledst" ]; then + if cmp -s $vncModule $moduledst/`basename $vncModule`; then + echo "`basename $vncModule` hasn't changed" + else + echo "Copying $vncModule to $moduledst" + cp -pf $vncModule $moduledst + chmod 0555 $moduledst/`basename $vncModule` + fi +fi diff --git a/unix/vncmkdepend/Makefile b/unix/vncmkdepend/Makefile new file mode 100644 index 00000000..32783681 --- /dev/null +++ b/unix/vncmkdepend/Makefile @@ -0,0 +1,4 @@ +SRCS = include.c main.c parse.c pr.c cppsetup.c ifparser.c +OBJS = $(SRCS:.c=.o) +vncmkdepend: $(OBJS) + $(CC) $^ -o $@ diff --git a/unix/vncmkdepend/README b/unix/vncmkdepend/README new file mode 100644 index 00000000..338b62c4 --- /dev/null +++ b/unix/vncmkdepend/README @@ -0,0 +1,39 @@ +vncmkdepend +=========== + +This code is taken from the X11R6 makedepend sources. All I have done is: + + * Remove all predefined symbols, include directories and other + platform-specific behaviour. Its behaviour should be the same on all + platforms. All symbols and include directories must be explicitly given on + the command line with -D and -I flags. + * Fix processing of numbers in #if expressions. + * Fix processing of -D flag. + * Fix C++ comment handling. + * Improve #error warnings. + * Change the output so that processing . produces .d + +The copyright on the code is: + +Copyright (c) 1993, 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 +CONNECTION 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 dealings +in this Software without prior written authorization from the X Consortium. diff --git a/unix/vncmkdepend/cppsetup.c b/unix/vncmkdepend/cppsetup.c new file mode 100644 index 00000000..bf1c4fc5 --- /dev/null +++ b/unix/vncmkdepend/cppsetup.c @@ -0,0 +1,242 @@ +/* $XConsortium: cppsetup.c,v 1.13 94/04/17 20:10:32 gildea Exp $ */ +/* + +Copyright (c) 1993, 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 +CONNECTION 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 dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +#include "def.h" + +#ifdef CPP +/* + * This file is strictly for the sake of cpy.y and yylex.c (if + * you indeed have the source for cpp). + */ +#define IB 1 +#define SB 2 +#define NB 4 +#define CB 8 +#define QB 16 +#define WB 32 +#define SALT '#' +#if pdp11 | vax | ns16000 | mc68000 | ibm032 +#define COFF 128 +#else +#define COFF 0 +#endif +/* + * These variables used by cpy.y and yylex.c + */ +extern char *outp, *inp, *newp, *pend; +extern char *ptrtab; +extern char fastab[]; +extern char slotab[]; + +/* + * cppsetup + */ +struct filepointer *currentfile; +struct inclist *currentinc; + +cppsetup(line, filep, inc) + register char *line; + register struct filepointer *filep; + register struct inclist *inc; +{ + register char *p, savec; + static boolean setupdone = FALSE; + boolean value; + + if (!setupdone) { + cpp_varsetup(); + setupdone = TRUE; + } + + currentfile = filep; + currentinc = inc; + inp = newp = line; + for (p=newp; *p; p++) + ; + + /* + * put a newline back on the end, and set up pend, etc. + */ + *p++ = '\n'; + savec = *p; + *p = '\0'; + pend = p; + + ptrtab = slotab+COFF; + *--inp = SALT; + outp=inp; + value = yyparse(); + *p = savec; + return(value); +} + +struct symtab *lookup(symbol) + char *symbol; +{ + static struct symtab undefined; + struct symtab *sp; + + sp = isdefined(symbol, currentinc, NULL); + if (sp == NULL) { + sp = &undefined; + sp->s_value = NULL; + } + return (sp); +} + +pperror(tag, x0,x1,x2,x3,x4) + int tag,x0,x1,x2,x3,x4; +{ + warning("\"%s\", line %d: ", currentinc->i_file, currentfile->f_line); + warning(x0,x1,x2,x3,x4); +} + + +yyerror(s) + register char *s; +{ + fatalerr("Fatal error: %s\n", s); +} +#else /* not CPP */ + +#include "ifparser.h" +struct _parse_data { + struct filepointer *filep; + struct inclist *inc; + const char *line; +}; + +static const char * +_my_if_errors (ip, cp, expecting) + IfParser *ip; + const char *cp; + const char *expecting; +{ + struct _parse_data *pd = (struct _parse_data *) ip->data; + int lineno = pd->filep->f_line; + char *filename = pd->inc->i_file; + char prefix[300]; + int prefixlen; + int i; + + sprintf (prefix, "\"%s\":%d", filename, lineno); + prefixlen = strlen(prefix); + fprintf (stderr, "%s: %s", prefix, pd->line); + i = cp - pd->line; + if (i > 0 && pd->line[i-1] != '\n') { + putc ('\n', stderr); + } + for (i += prefixlen + 3; i > 0; i--) { + putc (' ', stderr); + } + fprintf (stderr, "^--- expecting %s\n", expecting); + return NULL; +} + + +#define MAXNAMELEN 256 + +static struct symtab * +_lookup_variable (ip, var, len) + IfParser *ip; + const char *var; + int len; +{ + char tmpbuf[MAXNAMELEN + 1]; + struct _parse_data *pd = (struct _parse_data *) ip->data; + + if (len > MAXNAMELEN) + return 0; + + strncpy (tmpbuf, var, len); + tmpbuf[len] = '\0'; + return isdefined (tmpbuf, pd->inc, NULL); +} + + +static int +_my_eval_defined (ip, var, len) + IfParser *ip; + const char *var; + int len; +{ + if (_lookup_variable (ip, var, len)) + return 1; + else + return 0; +} + +#define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_') + +static int +_my_eval_variable (ip, var, len) + IfParser *ip; + const char *var; + int len; +{ + struct symtab *s; + + s = _lookup_variable (ip, var, len); + if (!s) + return 0; + do { + var = s->s_value; + if (!isvarfirstletter(*var)) + break; + s = _lookup_variable (ip, var, strlen(var)); + } while (s); + + return atoi(var); +} + + +cppsetup(line, filep, inc) + register char *line; + register struct filepointer *filep; + register struct inclist *inc; +{ + IfParser ip; + struct _parse_data pd; + int val = 0; + + pd.filep = filep; + pd.inc = inc; + pd.line = line; + ip.funcs.handle_error = _my_if_errors; + ip.funcs.eval_defined = _my_eval_defined; + ip.funcs.eval_variable = _my_eval_variable; + ip.data = (char *) &pd; + + (void) ParseIfExpression (&ip, line, &val); + if (val) + return IF; + else + return IFFALSE; +} +#endif /* CPP */ + diff --git a/unix/vncmkdepend/def.h b/unix/vncmkdepend/def.h new file mode 100644 index 00000000..8fb4c23f --- /dev/null +++ b/unix/vncmkdepend/def.h @@ -0,0 +1,140 @@ +/* $XConsortium: def.h,v 1.25 94/04/17 20:10:33 gildea Exp $ */ +/* + +Copyright (c) 1993, 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 +CONNECTION 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 dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +#include +#include +#ifndef X_NOT_POSIX +#ifndef _POSIX_SOURCE +#define _POSIX_SOURCE +#endif +#endif +#include +#include +#include + +#define MAXDEFINES 512 +#define MAXFILES 512 +#define MAXDIRS 64 +#define SYMTABINC 10 /* must be > 1 for define() to work right */ +#define TRUE 1 +#define FALSE 0 + +/* the following must match the directives table in main.c */ +#define IF 0 +#define IFDEF 1 +#define IFNDEF 2 +#define ELSE 3 +#define ENDIF 4 +#define DEFINE 5 +#define UNDEF 6 +#define INCLUDE 7 +#define LINE 8 +#define PRAGMA 9 +#define ERROR 10 +#define IDENT 11 +#define SCCS 12 +#define ELIF 13 +#define EJECT 14 +#define IFFALSE 15 /* pseudo value --- never matched */ +#define ELIFFALSE 16 /* pseudo value --- never matched */ +#define INCLUDEDOT 17 /* pseudo value --- never matched */ +#define IFGUESSFALSE 18 /* pseudo value --- never matched */ +#define ELIFGUESSFALSE 19 /* pseudo value --- never matched */ + +#ifdef DEBUG +extern int _debugmask; +/* + * debug levels are: + * + * 0 show ifn*(def)*,endif + * 1 trace defined/!defined + * 2 show #include + * 3 show #include SYMBOL + * 4-6 unused + */ +#define debug(level,arg) { if (_debugmask & (1 << level)) warning arg; } +#else +#define debug(level,arg) /**/ +#endif /* DEBUG */ + +typedef unsigned char boolean; + +struct symtab { + char *s_name; + char *s_value; +}; + +struct inclist { + char *i_incstring; /* string from #include line */ + char *i_file; /* path name of the include file */ + struct inclist **i_list; /* list of files it itself includes */ + int i_listlen; /* length of i_list */ + struct symtab *i_defs; /* symbol table for this file */ + int i_ndefs; /* current # defines */ + int i_deflen; /* amount of space in table */ + boolean i_defchecked; /* whether defines have been checked */ + boolean i_notified; /* whether we have revealed includes */ + boolean i_marked; /* whether it's in the makefile */ + boolean i_searched; /* whether we have read this */ + boolean i_included_sym; /* whether #include SYMBOL was found */ + /* Can't use i_list if TRUE */ +}; + +struct filepointer { + char *f_p; + char *f_base; + char *f_end; + long f_len; + long f_line; +}; + +#ifndef X_NOT_STDC_ENV +#include +#if defined(macII) && !defined(__STDC__) /* stdlib.h fails to define these */ +char *malloc(), *realloc(); +#endif /* macII */ +#else +char *malloc(); +char *realloc(); +#endif + +char *copy(); +char *base_name(); +char *getline(); +struct symtab *slookup(); +struct symtab *isdefined(); +struct symtab *fdefined(); +struct filepointer *getfile(); +struct inclist *newinclude(); +struct inclist *inc_path(); + +#if NeedVarargsPrototypes +extern fatalerr(char *, ...); +extern warning(char *, ...); +extern warning1(char *, ...); +#endif diff --git a/unix/vncmkdepend/ifparser.c b/unix/vncmkdepend/ifparser.c new file mode 100644 index 00000000..60740bcc --- /dev/null +++ b/unix/vncmkdepend/ifparser.c @@ -0,0 +1,445 @@ +/* + * $XConsortium: ifparser.c,v 1.7 94/01/18 21:30:50 rws Exp $ + * + * Copyright 1992 Network Computing Devices, Inc. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Network Computing Devices may not be + * used in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Network Computing Devices makes + * no representations about the suitability of this software for any purpose. + * It is provided ``as is'' without express or implied warranty. + * + * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Jim Fulton + * Network Computing Devices, Inc. + * + * Simple if statement processor + * + * This module can be used to evaluate string representations of C language + * if constructs. It accepts the following grammar: + * + * EXPRESSION := VALUE + * | VALUE BINOP EXPRESSION + * + * VALUE := '(' EXPRESSION ')' + * | '!' VALUE + * | '-' VALUE + * | 'defined' '(' variable ')' + * | 'defined' variable + * | # variable '(' variable-list ')' + * | variable + * | number + * + * BINOP := '*' | '/' | '%' + * | '+' | '-' + * | '<<' | '>>' + * | '<' | '>' | '<=' | '>=' + * | '==' | '!=' + * | '&' | '|' + * | '&&' | '||' + * + * The normal C order of precidence is supported. + * + * + * External Entry Points: + * + * ParseIfExpression parse a string for #if + */ + +#include "ifparser.h" +#include + +/**************************************************************************** + Internal Macros and Utilities for Parser + ****************************************************************************/ + +#define DO(val) if (!(val)) return NULL +#define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff)) +#define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++ +#define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_') + + +static const char * +parse_variable (g, cp, varp) + IfParser *g; + const char *cp; + const char **varp; +{ + SKIPSPACE (cp); + + if (!isvarfirstletter (*cp)) + return CALLFUNC(g, handle_error) (g, cp, "variable name"); + + *varp = cp; + /* EMPTY */ + for (cp++; isalnum(*cp) || *cp == '_'; cp++) ; + return cp; +} + + +static const char * +parse_number (g, cp, valp) + IfParser *g; + const char *cp; + int *valp; +{ + SKIPSPACE (cp); + + if (!isdigit(*cp)) + return CALLFUNC(g, handle_error) (g, cp, "number"); + + *valp = strtol(cp, &cp, 0); + return cp; +} + + +static const char * +parse_value (g, cp, valp) + IfParser *g; + const char *cp; + int *valp; +{ + const char *var; + + *valp = 0; + + SKIPSPACE (cp); + if (!*cp) + return cp; + + switch (*cp) { + case '(': + DO (cp = ParseIfExpression (g, cp + 1, valp)); + SKIPSPACE (cp); + if (*cp != ')') + return CALLFUNC(g, handle_error) (g, cp, ")"); + + return cp + 1; /* skip the right paren */ + + case '!': + DO (cp = parse_value (g, cp + 1, valp)); + *valp = !(*valp); + return cp; + + case '-': + DO (cp = parse_value (g, cp + 1, valp)); + *valp = -(*valp); + return cp; + + case '#': + DO (cp = parse_variable (g, cp + 1, &var)); + SKIPSPACE (cp); + if (*cp != '(') + return CALLFUNC(g, handle_error) (g, cp, "("); + do { + DO (cp = parse_variable (g, cp + 1, &var)); + SKIPSPACE (cp); + } while (*cp && *cp != ')'); + if (*cp != ')') + return CALLFUNC(g, handle_error) (g, cp, ")"); + *valp = 1; /* XXX */ + return cp + 1; + + case 'd': + if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) { + int paren = 0; + cp += 7; + SKIPSPACE (cp); + if (*cp == '(') { + paren = 1; + cp++; + } + DO (cp = parse_variable (g, cp, &var)); + SKIPSPACE (cp); + if (paren && *cp != ')') + return CALLFUNC(g, handle_error) (g, cp, ")"); + *valp = (*(g->funcs.eval_defined)) (g, var, cp - var); + return cp + paren; /* skip the right paren */ + } + /* fall out */ + } + + if (isdigit(*cp)) { + DO (cp = parse_number (g, cp, valp)); + } else if (!isvarfirstletter(*cp)) + return CALLFUNC(g, handle_error) (g, cp, "variable or number"); + else { + DO (cp = parse_variable (g, cp, &var)); + *valp = (*(g->funcs.eval_variable)) (g, var, cp - var); + } + + return cp; +} + + + +static const char * +parse_product (g, cp, valp) + IfParser *g; + const char *cp; + int *valp; +{ + int rightval; + + DO (cp = parse_value (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '*': + DO (cp = parse_product (g, cp + 1, &rightval)); + *valp = (*valp * rightval); + break; + + case '/': + DO (cp = parse_product (g, cp + 1, &rightval)); + *valp = (*valp / rightval); + break; + + case '%': + DO (cp = parse_product (g, cp + 1, &rightval)); + *valp = (*valp % rightval); + break; + } + return cp; +} + + +static const char * +parse_sum (g, cp, valp) + IfParser *g; + const char *cp; + int *valp; +{ + int rightval; + + DO (cp = parse_product (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '+': + DO (cp = parse_sum (g, cp + 1, &rightval)); + *valp = (*valp + rightval); + break; + + case '-': + DO (cp = parse_sum (g, cp + 1, &rightval)); + *valp = (*valp - rightval); + break; + } + return cp; +} + + +static const char * +parse_shift (g, cp, valp) + IfParser *g; + const char *cp; + int *valp; +{ + int rightval; + + DO (cp = parse_sum (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '<': + if (cp[1] == '<') { + DO (cp = parse_shift (g, cp + 2, &rightval)); + *valp = (*valp << rightval); + } + break; + + case '>': + if (cp[1] == '>') { + DO (cp = parse_shift (g, cp + 2, &rightval)); + *valp = (*valp >> rightval); + } + break; + } + return cp; +} + + +static const char * +parse_inequality (g, cp, valp) + IfParser *g; + const char *cp; + int *valp; +{ + int rightval; + + DO (cp = parse_shift (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '<': + if (cp[1] == '=') { + DO (cp = parse_inequality (g, cp + 2, &rightval)); + *valp = (*valp <= rightval); + } else { + DO (cp = parse_inequality (g, cp + 1, &rightval)); + *valp = (*valp < rightval); + } + break; + + case '>': + if (cp[1] == '=') { + DO (cp = parse_inequality (g, cp + 2, &rightval)); + *valp = (*valp >= rightval); + } else { + DO (cp = parse_inequality (g, cp + 1, &rightval)); + *valp = (*valp > rightval); + } + break; + } + return cp; +} + + +static const char * +parse_equality (g, cp, valp) + IfParser *g; + const char *cp; + int *valp; +{ + int rightval; + + DO (cp = parse_inequality (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '=': + if (cp[1] == '=') + cp++; + DO (cp = parse_equality (g, cp + 1, &rightval)); + *valp = (*valp == rightval); + break; + + case '!': + if (cp[1] != '=') + break; + DO (cp = parse_equality (g, cp + 2, &rightval)); + *valp = (*valp != rightval); + break; + } + return cp; +} + + +static const char * +parse_band (g, cp, valp) + IfParser *g; + const char *cp; + int *valp; +{ + int rightval; + + DO (cp = parse_equality (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '&': + if (cp[1] != '&') { + DO (cp = parse_band (g, cp + 1, &rightval)); + *valp = (*valp & rightval); + } + break; + } + return cp; +} + + +static const char * +parse_bor (g, cp, valp) + IfParser *g; + const char *cp; + int *valp; +{ + int rightval; + + DO (cp = parse_band (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '|': + if (cp[1] != '|') { + DO (cp = parse_bor (g, cp + 1, &rightval)); + *valp = (*valp | rightval); + } + break; + } + return cp; +} + + +static const char * +parse_land (g, cp, valp) + IfParser *g; + const char *cp; + int *valp; +{ + int rightval; + + DO (cp = parse_bor (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '&': + if (cp[1] != '&') + return CALLFUNC(g, handle_error) (g, cp, "&&"); + DO (cp = parse_land (g, cp + 2, &rightval)); + *valp = (*valp && rightval); + break; + } + return cp; +} + + +static const char * +parse_lor (g, cp, valp) + IfParser *g; + const char *cp; + int *valp; +{ + int rightval; + + DO (cp = parse_land (g, cp, valp)); + SKIPSPACE (cp); + + switch (*cp) { + case '|': + if (cp[1] != '|') + return CALLFUNC(g, handle_error) (g, cp, "||"); + DO (cp = parse_lor (g, cp + 2, &rightval)); + *valp = (*valp || rightval); + break; + } + return cp; +} + + +/**************************************************************************** + External Entry Points + ****************************************************************************/ + +const char * +ParseIfExpression (g, cp, valp) + IfParser *g; + const char *cp; + int *valp; +{ + return parse_lor (g, cp, valp); +} + + diff --git a/unix/vncmkdepend/ifparser.h b/unix/vncmkdepend/ifparser.h new file mode 100644 index 00000000..c3337982 --- /dev/null +++ b/unix/vncmkdepend/ifparser.h @@ -0,0 +1,76 @@ +/* + * $XConsortium: ifparser.h,v 1.1 92/08/22 13:05:39 rws Exp $ + * + * Copyright 1992 Network Computing Devices, Inc. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Network Computing Devices may not be + * used in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Network Computing Devices makes + * no representations about the suitability of this software for any purpose. + * It is provided ``as is'' without express or implied warranty. + * + * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Jim Fulton + * Network Computing Devices, Inc. + * + * Simple if statement processor + * + * This module can be used to evaluate string representations of C language + * if constructs. It accepts the following grammar: + * + * EXPRESSION := VALUE + * | VALUE BINOP EXPRESSION + * + * VALUE := '(' EXPRESSION ')' + * | '!' VALUE + * | '-' VALUE + * | 'defined' '(' variable ')' + * | variable + * | number + * + * BINOP := '*' | '/' | '%' + * | '+' | '-' + * | '<<' | '>>' + * | '<' | '>' | '<=' | '>=' + * | '==' | '!=' + * | '&' | '|' + * | '&&' | '||' + * + * The normal C order of precidence is supported. + * + * + * External Entry Points: + * + * ParseIfExpression parse a string for #if + */ + +#include + +#define const /**/ +typedef int Bool; +#define False 0 +#define True 1 + +typedef struct _if_parser { + struct { /* functions */ + char *(*handle_error) (/* struct _if_parser *, const char *, + const char * */); + int (*eval_variable) (/* struct _if_parser *, const char *, int */); + int (*eval_defined) (/* struct _if_parser *, const char *, int */); + } funcs; + char *data; +} IfParser; + +char *ParseIfExpression (/* IfParser *, const char *, int * */); + diff --git a/unix/vncmkdepend/include.c b/unix/vncmkdepend/include.c new file mode 100644 index 00000000..d6cd139d --- /dev/null +++ b/unix/vncmkdepend/include.c @@ -0,0 +1,312 @@ +/* $XConsortium: include.c,v 1.17 94/12/05 19:33:08 gildea Exp $ */ +/* + +Copyright (c) 1993, 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 +CONNECTION 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 dealings +in this Software without prior written authorization from the X Consortium. + +*/ + + +#include "def.h" + +extern struct inclist inclist[ MAXFILES ], + *inclistp; +extern char *includedirs[ ]; +extern char *notdotdot[ ]; +extern boolean show_where_not; +extern boolean warn_multiple; + +struct inclist *inc_path(file, include, dot) + register char *file, + *include; + boolean dot; +{ + static char path[ BUFSIZ ]; + register char **pp, *p; + register struct inclist *ip; + struct stat st; + boolean found = FALSE; + + /* + * Check all previously found include files for a path that + * has already been expanded. + */ + for (ip = inclist; ip->i_file; ip++) + if ((strcmp(ip->i_incstring, include) == 0) && !ip->i_included_sym) + { + found = TRUE; + break; + } + + /* + * If the path was surrounded by "" or is an absolute path, + * then check the exact path provided. + */ + if (!found && (dot || *include == '/')) { + if (stat(include, &st) == 0) { + ip = newinclude(include, include); + found = TRUE; + } + else if (show_where_not) + warning1("\tnot in %s\n", include); + } + + /* + * See if this include file is in the directory of the + * file being compiled. + */ + if (!found) { + for (p=file+strlen(file); p>file; p--) + if (*p == '/') + break; + if (p == file) + strcpy(path, include); + else { + strncpy(path, file, (p-file) + 1); + path[ (p-file) + 1 ] = '\0'; + strcpy(path + (p-file) + 1, include); + } + remove_dotdot(path); + if (stat(path, &st) == 0) { + ip = newinclude(path, include); + found = TRUE; + } + else if (show_where_not) + warning1("\tnot in %s\n", path); + } + + /* + * Check the include directories specified. (standard include dir + * should be at the end.) + */ + if (!found) + for (pp = includedirs; *pp; pp++) { +#ifdef WIN32 + sprintf(path, "%s\\%s", *pp, include); +#else + sprintf(path, "%s/%s", *pp, include); +#endif + remove_dotdot(path); + if (stat(path, &st) == 0) { + ip = newinclude(path, include); + found = TRUE; + break; + } + else if (show_where_not) + warning1("\tnot in %s\n", path); + } + + if (!found) + ip = NULL; + return(ip); +} + +/* + * Occasionally, pathnames are created that look like .../x/../y + * Any of the 'x/..' sequences within the name can be eliminated. + * (but only if 'x' is not a symbolic link!!) + */ +remove_dotdot(path) + char *path; +{ + register char *end, *from, *to, **cp; + char *components[ MAXFILES ], + newpath[ BUFSIZ ]; + boolean component_copied; + + /* + * slice path up into components. + */ + to = newpath; + if (*path == '/') + *to++ = '/'; + *to = '\0'; + cp = components; + for (from=end=path; *end; end++) + if (*end == '/') { + while (*end == '/') + *end++ = '\0'; + if (*from) + *cp++ = from; + from = end; + } + *cp++ = from; + *cp = NULL; + + /* + * Recursively remove all 'x/..' component pairs. + */ + cp = components; + while(*cp) { + if (!isdot(*cp) && !isdotdot(*cp) && isdotdot(*(cp+1)) + && !issymbolic(newpath, *cp)) + { + char **fp = cp + 2; + char **tp = cp; + + do + *tp++ = *fp; /* move all the pointers down */ + while (*fp++); + if (cp != components) + cp--; /* go back and check for nested ".." */ + } else { + cp++; + } + } + /* + * Concatenate the remaining path elements. + */ + cp = components; + component_copied = FALSE; + while(*cp) { + if (component_copied) + *to++ = '/'; + component_copied = TRUE; + for (from = *cp; *from; ) + *to++ = *from++; + *to = '\0'; + cp++; + } + *to++ = '\0'; + + /* + * copy the reconstituted path back to our pointer. + */ + strcpy(path, newpath); +} + +isdot(p) + register char *p; +{ + if(p && *p++ == '.' && *p++ == '\0') + return(TRUE); + return(FALSE); +} + +isdotdot(p) + register char *p; +{ + if(p && *p++ == '.' && *p++ == '.' && *p++ == '\0') + return(TRUE); + return(FALSE); +} + +issymbolic(dir, component) + register char *dir, *component; +{ +#ifdef S_IFLNK + struct stat st; + char buf[ BUFSIZ ], **pp; + + sprintf(buf, "%s%s%s", dir, *dir ? "/" : "", component); + for (pp=notdotdot; *pp; pp++) + if (strcmp(*pp, buf) == 0) + return (TRUE); + if (lstat(buf, &st) == 0 + && (st.st_mode & S_IFMT) == S_IFLNK) { + *pp++ = copy(buf); + if (pp >= ¬dotdot[ MAXDIRS ]) + fatalerr("out of .. dirs, increase MAXDIRS\n"); + return(TRUE); + } +#endif + return(FALSE); +} + +/* + * Add an include file to the list of those included by 'file'. + */ +struct inclist *newinclude(newfile, incstring) + register char *newfile, *incstring; +{ + register struct inclist *ip; + + /* + * First, put this file on the global list of include files. + */ + ip = inclistp++; + if (inclistp == inclist + MAXFILES - 1) + fatalerr("out of space: increase MAXFILES\n"); + ip->i_file = copy(newfile); + ip->i_included_sym = FALSE; + if (incstring == NULL) + ip->i_incstring = ip->i_file; + else + ip->i_incstring = copy(incstring); + + return(ip); +} + +included_by(ip, newfile) + register struct inclist *ip, *newfile; +{ + register i; + + if (ip == NULL) + return; + /* + * Put this include file (newfile) on the list of files included + * by 'file'. If 'file' is NULL, then it is not an include + * file itself (i.e. was probably mentioned on the command line). + * If it is already on the list, don't stick it on again. + */ + if (ip->i_list == NULL) + ip->i_list = (struct inclist **) + malloc(sizeof(struct inclist *) * ++ip->i_listlen); + else { + for (i=0; ii_listlen; i++) + if (ip->i_list[ i ] == newfile) { + i = strlen(newfile->i_file); + if (!ip->i_included_sym && + !(i > 2 && + newfile->i_file[i-1] == 'c' && + newfile->i_file[i-2] == '.')) + { + /* only bitch if ip has */ + /* no #include SYMBOL lines */ + /* and is not a .c file */ + if (warn_multiple) + { + warning("%s includes %s more than once!\n", + ip->i_file, newfile->i_file); + warning1("Already have\n"); + for (i=0; ii_listlen; i++) + warning1("\t%s\n", ip->i_list[i]->i_file); + } + } + return; + } + ip->i_list = (struct inclist **) realloc(ip->i_list, + sizeof(struct inclist *) * ++ip->i_listlen); + } + ip->i_list[ ip->i_listlen-1 ] = newfile; +} + +inc_clean () +{ + register struct inclist *ip; + + for (ip = inclist; ip < inclistp; ip++) { + ip->i_marked = FALSE; + } +} diff --git a/unix/vncmkdepend/main.c b/unix/vncmkdepend/main.c new file mode 100644 index 00000000..73057ae7 --- /dev/null +++ b/unix/vncmkdepend/main.c @@ -0,0 +1,593 @@ +/* $XConsortium: main.c,v 1.84 94/11/30 16:10:44 kaleb Exp $ */ +/* + +Copyright (c) 1993, 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 +CONNECTION 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 dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +#include "def.h" +#ifdef hpux +#define sigvec sigvector +#endif /* hpux */ + +#ifdef X_POSIX_C_SOURCE +#define _POSIX_C_SOURCE X_POSIX_C_SOURCE +#include +#undef _POSIX_C_SOURCE +#else +#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE) +#include +#else +#define _POSIX_SOURCE +#include +#undef _POSIX_SOURCE +#endif +#endif + +#if NeedVarargsPrototypes +#include +#endif + +#ifdef DEBUG +int _debugmask; +#endif + +char *ProgramName; + +char *directives[] = { + "if", + "ifdef", + "ifndef", + "else", + "endif", + "define", + "undef", + "include", + "line", + "pragma", + "error", + "ident", + "sccs", + "elif", + "eject", + NULL +}; + +struct symtab predefs[] = { {NULL, NULL} }; + +struct inclist inclist[ MAXFILES ], + *inclistp = inclist, + maininclist; + +char *filelist[ MAXFILES ]; +char *includedirs[ MAXDIRS + 1 ]; +char *notdotdot[ MAXDIRS ]; +char *objprefix = ""; +char *objsuffix = ".o"; +int width = 78; +boolean append = FALSE; +boolean printed = FALSE; +boolean verbose = FALSE; +boolean show_where_not = FALSE; +boolean warn_multiple = FALSE; /* Warn on multiple includes of same file */ + +static +#ifdef SIGNALRETURNSINT +int +#else +void +#endif +catch (sig) + int sig; +{ + fflush (stdout); + fatalerr ("got signal %d\n", sig); +} + +#if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) || defined(__nextstep__) +#define USGISH +#endif + +#ifndef USGISH +#ifndef _POSIX_SOURCE +#define sigaction sigvec +#define sa_handler sv_handler +#define sa_mask sv_mask +#define sa_flags sv_flags +#endif +struct sigaction sig_act; +#endif /* USGISH */ + +main(argc, argv) + int argc; + char **argv; +{ + register char **fp = filelist; + register char **incp = includedirs; + register char *p; + register struct inclist *ip; + char *makefile = NULL; + struct filepointer *filecontent; + struct symtab *psymp = predefs; + char *endmarker = NULL; + char *defincdir = NULL; + + ProgramName = argv[0]; + + while (psymp->s_name) + { + define2(psymp->s_name, psymp->s_value, &maininclist); + psymp++; + } + if (argc == 2 && argv[1][0] == '@') { + struct stat ast; + int afd; + char *args; + char **nargv; + int nargc; + char quotechar = '\0'; + + nargc = 1; + if ((afd = open(argv[1]+1, O_RDONLY)) < 0) + fatalerr("cannot open \"%s\"\n", argv[1]+1); + fstat(afd, &ast); + args = (char *)malloc(ast.st_size + 1); + if ((ast.st_size = read(afd, args, ast.st_size)) < 0) + fatalerr("failed to read %s\n", argv[1]+1); + args[ast.st_size] = '\0'; + close(afd); + for (p = args; *p; p++) { + if (quotechar) { + if (quotechar == '\\' || + (*p == quotechar && p[-1] != '\\')) + quotechar = '\0'; + continue; + } + switch (*p) { + case '\\': + case '"': + case '\'': + quotechar = *p; + break; + case ' ': + case '\n': + *p = '\0'; + if (p > args && p[-1]) + nargc++; + break; + } + } + if (p[-1]) + nargc++; + nargv = (char **)malloc(nargc * sizeof(char *)); + nargv[0] = argv[0]; + argc = 1; + for (p = args; argc < nargc; p += strlen(p) + 1) + if (*p) nargv[argc++] = p; + argv = nargv; + } + for(argc--, argv++; argc; argc--, argv++) { + /* if looking for endmarker then check before parsing */ + if (endmarker && strcmp (endmarker, *argv) == 0) { + endmarker = NULL; + continue; + } + if (**argv != '-') { + /* treat +thing as an option for C++ */ + if (endmarker && **argv == '+') + continue; + *fp++ = argv[0]; + continue; + } + switch(argv[0][1]) { + case '-': + endmarker = &argv[0][2]; + if (endmarker[0] == '\0') endmarker = "--"; + break; + case 'D': + { + int offset = 2; + if (argv[0][2] == '\0') { + argv++; + argc--; + offset = 0; + } + for (p=argv[0] + offset; *p ; p++) + if (*p == '=') { + *p = ' '; + break; + } + define(argv[0] + offset, &maininclist); + break; + } + case 'I': + if (incp >= includedirs + MAXDIRS) + fatalerr("Too many -I flags.\n"); + *incp++ = argv[0]+2; + if (**(incp-1) == '\0') { + *(incp-1) = *(++argv); + argc--; + } + break; + case 'Y': + defincdir = argv[0]+2; + break; + /* do not use if endmarker processing */ + case 'a': + if (endmarker) break; + append = TRUE; + break; + case 'w': + if (endmarker) break; + if (argv[0][2] == '\0') { + argv++; + argc--; + width = atoi(argv[0]); + } else + width = atoi(argv[0]+2); + break; + case 'o': + if (endmarker) break; + if (argv[0][2] == '\0') { + argv++; + argc--; + objsuffix = argv[0]; + } else + objsuffix = argv[0]+2; + break; + case 'p': + if (endmarker) break; + if (argv[0][2] == '\0') { + argv++; + argc--; + objprefix = argv[0]; + } else + objprefix = argv[0]+2; + break; + case 'v': + if (endmarker) break; + verbose = TRUE; +#ifdef DEBUG + if (argv[0][2]) + _debugmask = atoi(argv[0]+2); +#endif + break; + case 'm': + warn_multiple = TRUE; + break; + + /* Ignore -O, -g so we can just pass ${CFLAGS} to + makedepend + */ + case 'O': + case 'g': + break; + default: + if (endmarker) break; + /* fatalerr("unknown opt = %s\n", argv[0]); */ + warning("ignoring option %s\n", argv[0]); + } + } + if (!defincdir) { + } else if (*defincdir) { + if (incp >= includedirs + MAXDIRS) + fatalerr("Too many -I flags.\n"); + *incp++ = defincdir; + } + + /* + * catch signals. + */ +#ifdef USGISH +/* should really reset SIGINT to SIG_IGN if it was. */ +#ifdef SIGHUP + signal (SIGHUP, catch); +#endif + signal (SIGINT, catch); +#ifdef SIGQUIT + signal (SIGQUIT, catch); +#endif + signal (SIGILL, catch); +#ifdef SIGBUS + signal (SIGBUS, catch); +#endif + signal (SIGSEGV, catch); +#ifdef SIGSYS + signal (SIGSYS, catch); +#endif +#else + sig_act.sa_handler = catch; +#ifdef _POSIX_SOURCE + sigemptyset(&sig_act.sa_mask); + sigaddset(&sig_act.sa_mask, SIGINT); + sigaddset(&sig_act.sa_mask, SIGQUIT); +#ifdef SIGBUS + sigaddset(&sig_act.sa_mask, SIGBUS); +#endif + sigaddset(&sig_act.sa_mask, SIGILL); + sigaddset(&sig_act.sa_mask, SIGSEGV); + sigaddset(&sig_act.sa_mask, SIGHUP); + sigaddset(&sig_act.sa_mask, SIGPIPE); +#ifdef SIGSYS + sigaddset(&sig_act.sa_mask, SIGSYS); +#endif +#else + sig_act.sa_mask = ((1<<(SIGINT -1)) + |(1<<(SIGQUIT-1)) +#ifdef SIGBUS + |(1<<(SIGBUS-1)) +#endif + |(1<<(SIGILL-1)) + |(1<<(SIGSEGV-1)) + |(1<<(SIGHUP-1)) + |(1<<(SIGPIPE-1)) +#ifdef SIGSYS + |(1<<(SIGSYS-1)) +#endif + ); +#endif /* _POSIX_SOURCE */ + sig_act.sa_flags = 0; + sigaction(SIGHUP, &sig_act, (struct sigaction *)0); + sigaction(SIGINT, &sig_act, (struct sigaction *)0); + sigaction(SIGQUIT, &sig_act, (struct sigaction *)0); + sigaction(SIGILL, &sig_act, (struct sigaction *)0); +#ifdef SIGBUS + sigaction(SIGBUS, &sig_act, (struct sigaction *)0); +#endif + sigaction(SIGSEGV, &sig_act, (struct sigaction *)0); +#ifdef SIGSYS + sigaction(SIGSYS, &sig_act, (struct sigaction *)0); +#endif +#endif /* USGISH */ + + /* + * now peruse through the list of files. + */ + for(fp=filelist; *fp; fp++) { + char *base = base_name(*fp); + char *depfile = (char *)malloc(strlen(base) + 3); + sprintf(depfile,"%s.d",base); + if (!freopen(depfile, "wb", stdout)) + fatalerr("cannot open \"%s\"\n", depfile); + free(depfile); + free(base); + printed = FALSE; + filecontent = getfile(*fp); + ip = newinclude(*fp, (char *)NULL); + + find_includes(filecontent, ip, ip, 0, TRUE); + freefile(filecontent); + recursive_pr_include(ip, ip->i_file, base_name(*fp)); + inc_clean(); + if (printed) + printf("\n"); + } + exit(0); +} + +struct filepointer *getfile(file) + char *file; +{ + register int fd; + struct filepointer *content; + struct stat st; + + content = (struct filepointer *)malloc(sizeof(struct filepointer)); + if ((fd = open(file, O_RDONLY)) < 0) { + warning("cannot open \"%s\"\n", file); + content->f_p = content->f_base = content->f_end = (char *)malloc(1); + *content->f_p = '\0'; + return(content); + } + fstat(fd, &st); + content->f_base = (char *)malloc(st.st_size+1); + if (content->f_base == NULL) + fatalerr("cannot allocate mem\n"); + if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0) + fatalerr("failed to read %s\n", file); + close(fd); + content->f_len = st.st_size+1; + content->f_p = content->f_base; + content->f_end = content->f_base + st.st_size; + *content->f_end = '\0'; + content->f_line = 0; + return(content); +} + +freefile(fp) + struct filepointer *fp; +{ + free(fp->f_base); + free(fp); +} + +char *copy(str) + register char *str; +{ + register char *p = (char *)malloc(strlen(str) + 1); + + strcpy(p, str); + return(p); +} + +match(str, list) + register char *str, **list; +{ + register int i; + + for (i=0; *list; i++, list++) + if (strcmp(str, *list) == 0) + return(i); + return(-1); +} + +/* + * Get the next line. We only return lines beginning with '#' since that + * is all this program is ever interested in. + */ +char *getline(filep) + register struct filepointer *filep; +{ + register char *p, /* walking pointer */ + *eof, /* end of file pointer */ + *bol; /* beginning of line pointer */ + register lineno; /* line number */ + + p = filep->f_p; + eof = filep->f_end; + if (p >= eof) + return((char *)NULL); + lineno = filep->f_line; + + for(bol = p--; ++p < eof; ) { + if (*p == '/' && *(p+1) == '*') { /* consume comments */ + *p++ = ' ', *p++ = ' '; + while (*p) { + if (*p == '*' && *(p+1) == '/') { + *p++ = ' ', *p = ' '; + break; + } + else if (*p == '\n') + lineno++; + *p++ = ' '; + } + continue; + } + else if (*p == '/' && *(p+1) == '/') { /* consume comments */ + *p++ = ' ', *p++ = ' '; + while (*p && *p != '\n') + *p++ = ' '; + p--; /* go back to before newline */ + lineno++; + continue; + } + else if (*p == '\\') { + if (*(p+1) == '\n') { + *p = ' '; + *(p+1) = ' '; + lineno++; + } + } + else if (*p == '\n') { + lineno++; + if (*bol == '#') { + register char *cp; + + *p++ = '\0'; + /* punt lines with just # (yacc generated) */ + for (cp = bol+1; + *cp && (*cp == ' ' || *cp == '\t'); cp++); + if (*cp) goto done; + } + bol = p+1; + } + } + if (*bol != '#') + bol = NULL; +done: + filep->f_p = p; + filep->f_line = lineno; + return(bol); +} + +/* + * Strip the file name down to what we want to see in the Makefile. + * It will have objprefix and objsuffix around it. + */ +char *base_name(file) + register char *file; +{ + register char *p; + + for(p=file+strlen(file); p>file && *p != '/' && *p != '\\'; p--) ; + if (p>file) p++; + file = copy(p); + for(p=file+strlen(file); p>file && *p != '.'; p--) ; + + if (*p == '.') + *p = '\0'; + return(file); +} + + +#if NeedVarargsPrototypes +fatalerr(char *msg, ...) +#else +/*VARARGS*/ +fatalerr(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9) + char *msg; +#endif +{ +#if NeedVarargsPrototypes + va_list args; +#endif + fprintf(stderr, "%s: error: ", ProgramName); +#if NeedVarargsPrototypes + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); +#else + fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9); +#endif + exit (1); +} + +#if NeedVarargsPrototypes +warning(char *msg, ...) +#else +/*VARARGS0*/ +warning(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9) + char *msg; +#endif +{ +#if NeedVarargsPrototypes + va_list args; +#endif + fprintf(stderr, "%s: warning: ", ProgramName); +#if NeedVarargsPrototypes + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); +#else + fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9); +#endif +} + +#if NeedVarargsPrototypes +warning1(char *msg, ...) +#else +/*VARARGS0*/ +warning1(msg,x1,x2,x3,x4,x5,x6,x7,x8,x9) + char *msg; +#endif +{ +#if NeedVarargsPrototypes + va_list args; + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); +#else + fprintf(stderr, msg,x1,x2,x3,x4,x5,x6,x7,x8,x9); +#endif +} diff --git a/unix/vncmkdepend/parse.c b/unix/vncmkdepend/parse.c new file mode 100644 index 00000000..3f9b2fec --- /dev/null +++ b/unix/vncmkdepend/parse.c @@ -0,0 +1,568 @@ +/* $XConsortium: parse.c,v 1.30 94/04/17 20:10:38 gildea Exp $ */ +/* + +Copyright (c) 1993, 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 +CONNECTION 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 dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +#include "def.h" + +extern char *directives[]; +extern struct inclist maininclist; + +find_includes(filep, file, file_red, recursion, failOK) + struct filepointer *filep; + struct inclist *file, *file_red; + int recursion; + boolean failOK; +{ + register char *line; + register int type; + boolean recfailOK; + + while (line = getline(filep)) { + switch(type = deftype(line, filep, file_red, file, TRUE)) { + case IF: + doif: + type = find_includes(filep, file, + file_red, recursion+1, failOK); + while ((type == ELIF) || (type == ELIFFALSE) || + (type == ELIFGUESSFALSE)) + type = gobble(filep, file, file_red); + if (type == ELSE) + gobble(filep, file, file_red); + break; + case IFFALSE: + case IFGUESSFALSE: + doiffalse: + if (type == IFGUESSFALSE || type == ELIFGUESSFALSE) + recfailOK = TRUE; + else + recfailOK = failOK; + type = gobble(filep, file, file_red); + if (type == ELSE) + find_includes(filep, file, + file_red, recursion+1, recfailOK); + else + if (type == ELIF) + goto doif; + else + if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE)) + goto doiffalse; + break; + case IFDEF: + case IFNDEF: + if ((type == IFDEF && isdefined(line, file_red, NULL)) + || (type == IFNDEF && !isdefined(line, file_red, NULL))) { + debug(1,(type == IFNDEF ? + "line %d: %s !def'd in %s via %s%s\n" : "", + filep->f_line, line, + file->i_file, file_red->i_file, ": doit")); + type = find_includes(filep, file, + file_red, recursion+1, failOK); + while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE) + type = gobble(filep, file, file_red); + if (type == ELSE) + gobble(filep, file, file_red); + } + else { + debug(1,(type == IFDEF ? + "line %d: %s !def'd in %s via %s%s\n" : "", + filep->f_line, line, + file->i_file, file_red->i_file, ": gobble")); + type = gobble(filep, file, file_red); + if (type == ELSE) + find_includes(filep, file, + file_red, recursion+1, failOK); + else if (type == ELIF) + goto doif; + else if (type == ELIFFALSE || type == ELIFGUESSFALSE) + goto doiffalse; + } + break; + case ELSE: + case ELIFFALSE: + case ELIFGUESSFALSE: + case ELIF: + if (!recursion) + gobble(filep, file, file_red); + case ENDIF: + if (recursion) + return(type); + case DEFINE: + define(line, file); + break; + case UNDEF: + if (!*line) { + warning("%s, line %d: incomplete undef == \"%s\"\n", + file_red->i_file, filep->f_line, line); + break; + } + undefine(line, file_red); + break; + case INCLUDE: + add_include(filep, file, file_red, line, FALSE, failOK); + break; + case INCLUDEDOT: + add_include(filep, file, file_red, line, TRUE, failOK); + break; + case ERROR: + warning("(from %s) %s: %d: %s\n", + file_red->i_file, file->i_file, + filep->f_line, line); + break; + + case PRAGMA: + case IDENT: + case SCCS: + case EJECT: + break; + case -1: + warning("%s", file_red->i_file); + if (file_red != file) + warning1(" (reading %s)", file->i_file); + warning1(", line %d: unknown directive == \"%s\"\n", + filep->f_line, line); + break; + case -2: + warning("%s", file_red->i_file); + if (file_red != file) + warning1(" (reading %s)", file->i_file); + warning1(", line %d: incomplete include == \"%s\"\n", + filep->f_line, line); + break; + } + } + return(-1); +} + +gobble(filep, file, file_red) + register struct filepointer *filep; + struct inclist *file, *file_red; +{ + register char *line; + register int type; + + while (line = getline(filep)) { + switch(type = deftype(line, filep, file_red, file, FALSE)) { + case IF: + case IFFALSE: + case IFGUESSFALSE: + case IFDEF: + case IFNDEF: + type = gobble(filep, file, file_red); + while ((type == ELIF) || (type == ELIFFALSE) || + (type == ELIFGUESSFALSE)) + type = gobble(filep, file, file_red); + if (type == ELSE) + (void)gobble(filep, file, file_red); + break; + case ELSE: + case ENDIF: + debug(0,("%s, line %d: #%s\n", + file->i_file, filep->f_line, + directives[type])); + return(type); + case DEFINE: + case UNDEF: + case INCLUDE: + case INCLUDEDOT: + case PRAGMA: + case ERROR: + case IDENT: + case SCCS: + case EJECT: + break; + case ELIF: + case ELIFFALSE: + case ELIFGUESSFALSE: + return(type); + case -1: + warning("%s, line %d: unknown directive == \"%s\"\n", + file_red->i_file, filep->f_line, line); + break; + } + } + return(-1); +} + +/* + * Decide what type of # directive this line is. + */ +int deftype (line, filep, file_red, file, parse_it) + register char *line; + register struct filepointer *filep; + register struct inclist *file_red, *file; + int parse_it; +{ + register char *p; + char *directive, savechar; + register int ret; + + /* + * Parse the directive... + */ + directive=line+1; + while (*directive == ' ' || *directive == '\t') + directive++; + + p = directive; + while (*p >= 'a' && *p <= 'z') + p++; + savechar = *p; + *p = '\0'; + ret = match(directive, directives); + *p = savechar; + + /* If we don't recognize this compiler directive or we happen to just + * be gobbling up text while waiting for an #endif or #elif or #else + * in the case of an #elif we must check the zero_value and return an + * ELIF or an ELIFFALSE. + */ + + if (ret == ELIF && !parse_it) + { + while (*p == ' ' || *p == '\t') + p++; + /* + * parse an expression. + */ + debug(0,("%s, line %d: #elif %s ", + file->i_file, filep->f_line, p)); + ret = zero_value(p, filep, file_red); + if (ret != IF) + { + debug(0,("false...\n")); + if (ret == IFFALSE) + return(ELIFFALSE); + else + return(ELIFGUESSFALSE); + } + else + { + debug(0,("true...\n")); + return(ELIF); + } + } + + if (ret < 0 || ! parse_it) + return(ret); + + /* + * now decide how to parse the directive, and do it. + */ + while (*p == ' ' || *p == '\t') + p++; + switch (ret) { + case IF: + /* + * parse an expression. + */ + ret = zero_value(p, filep, file_red); + debug(0,("%s, line %d: %s #if %s\n", + file->i_file, filep->f_line, ret?"false":"true", p)); + break; + case IFDEF: + case IFNDEF: + debug(0,("%s, line %d: #%s %s\n", + file->i_file, filep->f_line, directives[ret], p)); + case UNDEF: + /* + * separate the name of a single symbol. + */ + while (isalnum(*p) || *p == '_') + *line++ = *p++; + *line = '\0'; + break; + case INCLUDE: + debug(2,("%s, line %d: #include %s\n", + file->i_file, filep->f_line, p)); + + /* Support ANSI macro substitution */ + { + struct symtab *sym = isdefined(p, file_red, NULL); + while (sym) { + p = sym->s_value; + debug(3,("%s : #includes SYMBOL %s = %s\n", + file->i_incstring, + sym -> s_name, + sym -> s_value)); + /* mark file as having included a 'soft include' */ + file->i_included_sym = TRUE; + sym = isdefined(p, file_red, NULL); + } + } + + /* + * Separate the name of the include file. + */ + while (*p && *p != '"' && *p != '<') + p++; + if (! *p) + return(-2); + if (*p++ == '"') { + ret = INCLUDEDOT; + while (*p && *p != '"') + *line++ = *p++; + } else + while (*p && *p != '>') + *line++ = *p++; + *line = '\0'; + break; + case DEFINE: + /* + * copy the definition back to the beginning of the line. + */ + strcpy (line, p); + break; + case ELSE: + case ENDIF: + case ELIF: + case PRAGMA: + case ERROR: + case IDENT: + case SCCS: + case EJECT: + debug(0,("%s, line %d: #%s\n", + file->i_file, filep->f_line, directives[ret])); + /* + * nothing to do. + */ + break; + } + return(ret); +} + +struct symtab *isdefined(symbol, file, srcfile) + register char *symbol; + struct inclist *file; + struct inclist **srcfile; +{ + register struct symtab *val; + + if (val = slookup(symbol, &maininclist)) { + debug(1,("%s defined on command line\n", symbol)); + if (srcfile != NULL) *srcfile = &maininclist; + return(val); + } + if (val = fdefined(symbol, file, srcfile)) + return(val); + debug(1,("%s not defined in %s\n", symbol, file->i_file)); + return(NULL); +} + +struct symtab *fdefined(symbol, file, srcfile) + register char *symbol; + struct inclist *file; + struct inclist **srcfile; +{ + register struct inclist **ip; + register struct symtab *val; + register int i; + static int recurse_lvl = 0; + + if (file->i_defchecked) + return(NULL); + file->i_defchecked = TRUE; + if (val = slookup(symbol, file)) + debug(1,("%s defined in %s as %s\n", symbol, file->i_file, val->s_value)); + if (val == NULL && file->i_list) + { + for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++) + if (val = fdefined(symbol, *ip, srcfile)) { + break; + } + } + else if (val != NULL && srcfile != NULL) *srcfile = file; + recurse_lvl--; + file->i_defchecked = FALSE; + + return(val); +} + +/* + * Return type based on if the #if expression evaluates to 0 + */ +zero_value(exp, filep, file_red) + register char *exp; + register struct filepointer *filep; + register struct inclist *file_red; +{ + if (cppsetup(exp, filep, file_red)) + return(IFFALSE); + else + return(IF); +} + +define(def, file) + char *def; + struct inclist *file; +{ + char *val; + + /* Separate symbol name and its value */ + val = def; + while (isalnum(*val) || *val == '_') + val++; + if (*val) + *val++ = '\0'; + while (*val == ' ' || *val == '\t') + val++; + + if (!*val) + val = "1"; + define2(def, val, file); +} + +define2(name, val, file) + char *name, *val; + struct inclist *file; +{ + int first, last, below; + register struct symtab *sp = NULL, *dest; + + /* Make space if it's needed */ + if (file->i_defs == NULL) + { + file->i_defs = (struct symtab *) + malloc(sizeof (struct symtab) * SYMTABINC); + file->i_deflen = SYMTABINC; + file->i_ndefs = 0; + } + else if (file->i_ndefs == file->i_deflen) + file->i_defs = (struct symtab *) + realloc(file->i_defs, + sizeof(struct symtab)*(file->i_deflen+=SYMTABINC)); + + if (file->i_defs == NULL) + fatalerr("malloc()/realloc() failure in insert_defn()\n"); + + below = first = 0; + last = file->i_ndefs - 1; + while (last >= first) + { + /* Fast inline binary search */ + register char *s1; + register char *s2; + register int middle = (first + last) / 2; + + /* Fast inline strchr() */ + s1 = name; + s2 = file->i_defs[middle].s_name; + while (*s1++ == *s2++) + if (s2[-1] == '\0') break; + + /* If exact match, set sp and break */ + if (*--s1 == *--s2) + { + sp = file->i_defs + middle; + break; + } + + /* If name > i_defs[middle] ... */ + if (*s1 > *s2) + { + below = first; + first = middle + 1; + } + /* else ... */ + else + { + below = last = middle - 1; + } + } + + /* Search is done. If we found an exact match to the symbol name, + just replace its s_value */ + if (sp != NULL) + { + free(sp->s_value); + sp->s_value = copy(val); + return; + } + + sp = file->i_defs + file->i_ndefs++; + dest = file->i_defs + below + 1; + while (sp > dest) + { + *sp = sp[-1]; + sp--; + } + sp->s_name = copy(name); + sp->s_value = copy(val); +} + +struct symtab *slookup(symbol, file) + register char *symbol; + register struct inclist *file; +{ + register int first = 0; + register int last = file->i_ndefs - 1; + + if (file) while (last >= first) + { + /* Fast inline binary search */ + register char *s1; + register char *s2; + register int middle = (first + last) / 2; + + /* Fast inline strchr() */ + s1 = symbol; + s2 = file->i_defs[middle].s_name; + while (*s1++ == *s2++) + if (s2[-1] == '\0') break; + + /* If exact match, we're done */ + if (*--s1 == *--s2) + { + return file->i_defs + middle; + } + + /* If symbol > i_defs[middle] ... */ + if (*s1 > *s2) + { + first = middle + 1; + } + /* else ... */ + else + { + last = middle - 1; + } + } + return(NULL); +} + +undefine(symbol, file) + char *symbol; + register struct inclist *file; +{ + register struct symtab *ptr; + struct inclist *srcfile; + while ((ptr = isdefined(symbol, file, &srcfile)) != NULL) + { + srcfile->i_ndefs--; + for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++) + *ptr = ptr[1]; + } +} diff --git a/unix/vncmkdepend/pr.c b/unix/vncmkdepend/pr.c new file mode 100644 index 00000000..318046d3 --- /dev/null +++ b/unix/vncmkdepend/pr.c @@ -0,0 +1,130 @@ +/* $XConsortium: pr.c,v 1.17 94/04/17 20:10:38 gildea Exp $ */ +/* + +Copyright (c) 1993, 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 +CONNECTION 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 dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +#include "def.h" + +extern struct inclist inclist[ MAXFILES ], + *inclistp; +extern char *objprefix; +extern char *objsuffix; +extern int width; +extern boolean printed; +extern boolean verbose; +extern boolean show_where_not; + +add_include(filep, file, file_red, include, dot, failOK) + struct filepointer *filep; + struct inclist *file, *file_red; + char *include; + boolean dot; +{ + register struct inclist *newfile; + register struct filepointer *content; + + /* + * First decide what the pathname of this include file really is. + */ + newfile = inc_path(file->i_file, include, dot); + if (newfile == NULL) { + if (failOK) + return; + if (file != file_red) + warning("%s (reading %s, line %d): ", + file_red->i_file, file->i_file, filep->f_line); + else + warning("%s, line %d: ", file->i_file, filep->f_line); + warning1("cannot find include file \"%s\"\n", include); + show_where_not = TRUE; + newfile = inc_path(file->i_file, include, dot); + show_where_not = FALSE; + } + + if (newfile) { + included_by(file, newfile); + if (!newfile->i_searched) { + newfile->i_searched = TRUE; + content = getfile(newfile->i_file); + find_includes(content, newfile, file_red, 0, failOK); + freefile(content); + } + } +} + +recursive_pr_include(head, file, base) + register struct inclist *head; + register char *file, *base; +{ + register int i; + + if (head->i_marked) + return; + head->i_marked = TRUE; + if (head->i_file != file) + pr(head, file, base); + for (i=0; ii_listlen; i++) + recursive_pr_include(head->i_list[ i ], file, base); +} + +pr(ip, file, base) + register struct inclist *ip; + char *file, *base; +{ + static char *lastfile; + register int len, i; + char buf[ BUFSIZ ]; +#ifdef WIN32 + char *transfile = TranslateFileNameD2U(ip->i_file,0); +#else + char *transfile = ip->i_file; +#endif + + printed = TRUE; + if (file != lastfile) { + lastfile = file; + sprintf(buf, "%s%s%s %s.d: %s", objprefix, base, objsuffix, + base, transfile); + } + else { + sprintf(buf, " \\\n %s", transfile); + } + fwrite(buf, strlen(buf), 1, stdout); + + /* + * If verbose is set, then print out what this file includes. + */ + if (! verbose || ip->i_list == NULL || ip->i_notified) + return; + ip->i_notified = TRUE; + lastfile = NULL; + printf("\n# %s includes:", transfile); + for (i=0; ii_listlen; i++) + printf("\n#\t%s", ip->i_list[ i ]->i_incstring); +#ifdef WIN32 + free(transfile); +#endif +} diff --git a/unix/vncpasswd/Makefile.in b/unix/vncpasswd/Makefile.in new file mode 100644 index 00000000..927a7b92 --- /dev/null +++ b/unix/vncpasswd/Makefile.in @@ -0,0 +1,18 @@ + +SRCS = vncpasswd.cxx + +OBJS = vncpasswd.o + +program = vncpasswd + +DEP_LIBS = ../rfb/librfb.a + +DIR_CPPFLAGS = -I$(top_srcdir) + +all:: $(program) + +$(program): $(OBJS) $(DEP_LIBS) + rm -f $(program) + $(CXXLD) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(DEP_LIBS) $(LIBS) + +# followed by boilerplate.mk diff --git a/unix/vncpasswd/vncpasswd.cxx b/unix/vncpasswd/vncpasswd.cxx new file mode 100644 index 00000000..e8898792 --- /dev/null +++ b/unix/vncpasswd/vncpasswd.cxx @@ -0,0 +1,138 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +using namespace rfb; + +char* prog; + +static void usage() +{ + fprintf(stderr,"usage: %s [file]\n",prog); + exit(1); +} + + +static void enableEcho(bool enable) { + termios attrs; + tcgetattr(fileno(stdin), &attrs); + if (enable) + attrs.c_lflag |= ECHO; + else + attrs.c_lflag &= ~ECHO; + attrs.c_lflag |= ECHONL; + tcsetattr(fileno(stdin), TCSAFLUSH, &attrs); +} + +static char* getpassword(const char* prompt) { + PlainPasswd buf(256); + fputs(prompt, stdout); + enableEcho(false); + char* result = fgets(buf.buf, 256, stdin); + enableEcho(true); + if (result) { + if (result[strlen(result)-1] == '\n') + result[strlen(result)-1] = 0; + return buf.takeBuf(); + } + return 0; +} + + +int main(int argc, char** argv) +{ + prog = argv[0]; + + char* fname = 0; + + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "-q") == 0) { // allowed for backwards compatibility + } else if (argv[i][0] == '-') { + usage(); + } else if (!fname) { + fname = argv[i]; + } else { + usage(); + } + } + + if (!fname) { + if (!getenv("HOME")) { + fprintf(stderr,"HOME is not set\n"); + exit(1); + } + fname = new char[strlen(getenv("HOME")) + 20]; + sprintf(fname, "%s/.vnc", getenv("HOME")); + mkdir(fname, 0777); + sprintf(fname, "%s/.vnc/passwd", getenv("HOME")); + } + + while (true) { + PlainPasswd passwd(getpassword("Password:")); + if (!passwd.buf) { + perror("getpassword error"); + exit(1); + } + if (strlen(passwd.buf) < 6) { + if (strlen(passwd.buf) == 0) { + fprintf(stderr,"Password not changed\n"); + exit(1); + } + fprintf(stderr,"Password must be at least 6 characters - try again\n"); + continue; + } + + PlainPasswd passwd2(getpassword("Verify:")); + if (!passwd2.buf) { + perror("getpass error"); + exit(1); + } + if (strcmp(passwd.buf, passwd2.buf) != 0) { + fprintf(stderr,"Passwords don't match - try again\n"); + continue; + } + + FILE* fp = fopen(fname,"w"); + if (!fp) { + fprintf(stderr,"Couldn't open %s for writing\n",fname); + exit(1); + } + chmod(fname, S_IRUSR|S_IWUSR); + + ObfuscatedPasswd obfuscated(passwd); + + if (fwrite(obfuscated.buf, obfuscated.length, 1, fp) != 1) { + fprintf(stderr,"Writing to %s failed\n",fname); + exit(1); + } + + fclose(fp); + + return 0; + } +} diff --git a/unix/vncpasswd/vncpasswd.man b/unix/vncpasswd/vncpasswd.man new file mode 100644 index 00000000..8fd68745 --- /dev/null +++ b/unix/vncpasswd/vncpasswd.man @@ -0,0 +1,43 @@ +.TH vncpasswd 1 "05 May 2006" "TightVNC" "Virtual Network Computing" +.SH NAME +vncpasswd \- change a VNC password +.SH SYNOPSIS +.B vncpasswd +.RI [ passwd-file ] +.SH DESCRIPTION +.B vncpasswd +allows you to set the password used to access VNC desktops. It stores an +obfuscated version of the password in the given file (default +$HOME/.vnc/passwd). The \fBvncserver\fP script runs \fBvncpasswd\fP the first +time you start a VNC desktop, and invokes \fBXvnc\fP with the appropriate +\fB\-rfbauth\fP option. \fBvncviewer\fP can also be given a password file to +use via the \fB\-passwd\fP option. + +The password must be at least six characters long, and only the first eight +characters are significant. Note that the stored password is \fBnot\fP +encrypted securely - anyone who has access to this file can trivially find out +the plaintext password, so \fBvncpasswd\fP always sets appropriate permissions +(read and write only by the owner). However, when accessing a VNC desktop a +challenge-response mechanism is used over the wire making it hard for anyone to +crack the password simply by snooping on the network. + +.SH FILES +.TP +$HOME/.vnc/passwd +Default location of the VNC password file. + +.SH SEE ALSO +.BR vncviewer (1), +.BR vncserver (1), +.BR Xvnc (1) +.BR vncconfig (1), +.br +http://www.tightvnc.com + +.SH AUTHOR +Tristan Richardson, RealVNC Ltd. + +VNC was originally developed by the RealVNC team while at Olivetti +Research Ltd / AT&T Laboratories Cambridge. TightVNC additions was +implemented by Constantin Kaplinsky. Many other people participated in +development, testing and support. diff --git a/unix/vncserver b/unix/vncserver new file mode 100755 index 00000000..16fe54a2 --- /dev/null +++ b/unix/vncserver @@ -0,0 +1,570 @@ +#!/usr/bin/env perl +# +# Copyright (C) 2002-2005 RealVNC Ltd. +# Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. +# +# This 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. +# +# This software is distributed in the hope that 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 software; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. +# + +# +# vncserver - wrapper script to start an X VNC server. +# + +# +# First make sure we're operating in a sane environment. +# + +&SanityCheck(); + +# +# Global variables. You may want to configure some of these for your site. +# + +$geometry = "1024x768"; +$depth = 16; +$vncJavaFiles = (((-d "/usr/share/vnc/classes") && "/usr/share/vnc/classes") || + ((-d "/usr/local/vnc/classes") && "/usr/local/vnc/classes")); +$vncUserDir = "$ENV{HOME}/.vnc"; +$xauthorityFile = "$ENV{XAUTHORITY}" || "$ENV{HOME}/.Xauthority"; + +$defaultXStartup + = ("#!/bin/sh\n\n". + "[ -r \$HOME/.Xresources ] && xrdb \$HOME/.Xresources\n". + "xsetroot -solid grey\n". + "vncconfig -iconic &\n". + "xterm -geometry 80x24+10+10 -ls -title \"\$VNCDESKTOP Desktop\" &\n". + "twm &\n"); + +chop($host = `uname -n`); + + +# Check command line options + +&ParseOptions("-geometry",1,"-depth",1,"-pixelformat",1,"-name",1,"-kill",1, + "-help",0,"-h",0,"--help",0); + +&Usage() if ($opt{'-help'} || $opt{'-h'} || $opt{'--help'}); + +&Kill() if ($opt{'-kill'}); + +# Uncomment this line if you want default geometry, depth and pixelformat +# to match the current X display: +# &GetXDisplayDefaults(); + +if ($opt{'-geometry'}) { + $geometry = $opt{'-geometry'}; +} +if ($opt{'-depth'}) { + $depth = $opt{'-depth'}; + $pixelformat = ""; +} +if ($opt{'-pixelformat'}) { + $pixelformat = $opt{'-pixelformat'}; +} + +&CheckGeometryAndDepth(); + + +# Create the user's vnc directory if necessary. + +if (!(-e $vncUserDir)) { + if (!mkdir($vncUserDir,0755)) { + die "$prog: Could not create $vncUserDir.\n"; + } +} + +# Make sure the user has a password. + +($z,$z,$mode) = stat("$vncUserDir/passwd"); +if (!(-e "$vncUserDir/passwd") || ($mode & 077)) { + warn "\nYou will require a password to access your desktops.\n\n"; + system("vncpasswd -q $vncUserDir/passwd"); + if (($? >> 8) != 0) { + exit 1; + } +} + +# Find display number. + +if ((@ARGV > 0) && ($ARGV[0] =~ /^:(\d+)$/)) { + $displayNumber = $1; + shift(@ARGV); + if (!&CheckDisplayNumber($displayNumber)) { + die "A VNC server is already running as :$displayNumber\n"; + } +} elsif ((@ARGV > 0) && ($ARGV[0] !~ /^-/)) { + &Usage(); +} else { + $displayNumber = &GetDisplayNumber(); +} + +$vncPort = 5900 + $displayNumber; + +$desktopLog = "$vncUserDir/$host:$displayNumber.log"; +unlink($desktopLog); + +# Make an X server cookie - use as the seed the sum of the current time, our +# PID and part of the encrypted form of the password. Ideally we'd use +# /dev/urandom, but that's only available on Linux. + +srand(time+$$+unpack("L",`cat $vncUserDir/passwd`)); +$cookie = ""; +for (1..16) { + $cookie .= sprintf("%02x", int(rand(256)) % 256); +} + +system("xauth -f $xauthorityFile add $host:$displayNumber . $cookie"); +system("xauth -f $xauthorityFile add $host/unix:$displayNumber . $cookie"); + +if ($opt{'-name'}) { + $desktopName = $opt{'-name'}; +} else { + $desktopName = "$host:$displayNumber ($ENV{USER})"; +} + +# Now start the X VNC Server + +$cmd = "Xvnc :$displayNumber"; +$cmd .= " -desktop " . "edString($desktopName); +$cmd .= " -httpd $vncJavaFiles" if ($vncJavaFiles); +$cmd .= " -auth $xauthorityFile"; +$cmd .= " -geometry $geometry" if ($geometry); +$cmd .= " -depth $depth" if ($depth); +$cmd .= " -pixelformat $pixelformat" if ($pixelformat); +$cmd .= " -rfbwait 30000"; +$cmd .= " -rfbauth $vncUserDir/passwd"; +$cmd .= " -rfbport $vncPort"; +$cmd .= " -pn"; + +# Add font path and color database stuff here, e.g.: +# +# $cmd .= " -fp /usr/lib/X11/fonts/misc/,/usr/lib/X11/fonts/75dpi/"; +# $cmd .= " -co /usr/lib/X11/rgb"; +# + +foreach $arg (@ARGV) { + $cmd .= " " . "edString($arg); +} +$cmd .= " >> " . "edString($desktopLog) . " 2>&1"; + +# Run $cmd and record the process ID. + +$pidFile = "$vncUserDir/$host:$displayNumber.pid"; +system("$cmd & echo \$! >$pidFile"); + +# Give Xvnc a chance to start up + +sleep(3); + +warn "\nNew '$desktopName' desktop is $host:$displayNumber\n\n"; + +# Create the user's xstartup script if necessary. + +if (!(-e "$vncUserDir/xstartup")) { + warn "Creating default startup script $vncUserDir/xstartup\n"; + open(XSTARTUP, ">$vncUserDir/xstartup"); + print XSTARTUP $defaultXStartup; + close(XSTARTUP); + chmod 0755, "$vncUserDir/xstartup"; +} + +# Run the X startup script. + +warn "Starting applications specified in $vncUserDir/xstartup\n"; +warn "Log file is $desktopLog\n\n"; + +# If the unix domain socket exists then use that (DISPLAY=:n) otherwise use +# TCP (DISPLAY=host:n) + +if (-e "/tmp/.X11-unix/X$displayNumber" || + -e "/usr/spool/sockets/X11/$displayNumber") +{ + $ENV{DISPLAY}= ":$displayNumber"; +} else { + $ENV{DISPLAY}= "$host:$displayNumber"; +} +$ENV{VNCDESKTOP}= $desktopName; + +system("$vncUserDir/xstartup >> " . "edString($desktopLog) . " 2>&1 &"); + +exit; + + +############################################################################### +# +# CheckGeometryAndDepth simply makes sure that the geometry and depth values +# are sensible. +# + +sub CheckGeometryAndDepth +{ + if ($geometry =~ /^(\d+)x(\d+)$/) { + $width = $1; $height = $2; + + if (($width<1) || ($height<1)) { + die "$prog: geometry $geometry is invalid\n"; + } + + while (($width % 4)!=0) { + $width = $width + 1; + } + + while (($height % 2)!=0) { + $height = $height + 1; + } + + $geometry = "${width}x$height"; + } else { + die "$prog: geometry $geometry is invalid\n"; + } + + if (($depth < 8) || ($depth > 32)) { + die "Depth must be between 8 and 32\n"; + } +} + + +# +# GetDisplayNumber gets the lowest available display number. A display number +# n is taken if something is listening on the VNC server port (5900+n) or the +# X server port (6000+n). +# + +sub GetDisplayNumber +{ + foreach $n (1..99) { + if (&CheckDisplayNumber($n)) { + return $n+0; # Bruce Mah's workaround for bug in perl 5.005_02 + } + } + + die "$prog: no free display number on $host.\n"; +} + + +# +# CheckDisplayNumber checks if the given display number is available. A +# display number n is taken if something is listening on the VNC server port +# (5900+n) or the X server port (6000+n). +# + +sub CheckDisplayNumber +{ + local ($n) = @_; + + socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n"; + eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))'; + if (!bind(S, pack('S n x12', $AF_INET, 6000 + $n))) { + close(S); + return 0; + } + close(S); + + socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n"; + eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))'; + if (!bind(S, pack('S n x12', $AF_INET, 5900 + $n))) { + close(S); + return 0; + } + close(S); + + if (-e "/tmp/.X$n-lock") { + warn "\nWarning: $host:$n is taken because of /tmp/.X$n-lock\n"; + warn "Remove this file if there is no X server $host:$n\n"; + return 0; + } + + if (-e "/tmp/.X11-unix/X$n") { + warn "\nWarning: $host:$n is taken because of /tmp/.X11-unix/X$n\n"; + warn "Remove this file if there is no X server $host:$n\n"; + return 0; + } + + if (-e "/usr/spool/sockets/X11/$n") { + warn("\nWarning: $host:$n is taken because of ". + "/usr/spool/sockets/X11/$n\n"); + warn "Remove this file if there is no X server $host:$n\n"; + return 0; + } + + return 1; +} + + +# +# GetXDisplayDefaults uses xdpyinfo to find out the geometry, depth and pixel +# format of the current X display being used. If successful, it sets the +# options as appropriate so that the X VNC server will use the same settings +# (minus an allowance for window manager decorations on the geometry). Using +# the same depth and pixel format means that the VNC server won't have to +# translate pixels when the desktop is being viewed on this X display (for +# TrueColor displays anyway). +# + +sub GetXDisplayDefaults +{ + local (@lines, @matchlines, $width, $height, $defaultVisualId, $i, + $red, $green, $blue); + + $wmDecorationWidth = 4; # a guess at typical size for window manager + $wmDecorationHeight = 24; # decoration size + + return if (!defined($ENV{DISPLAY})); + + @lines = `xdpyinfo 2>/dev/null`; + + return if ($? != 0); + + @matchlines = grep(/dimensions/, @lines); + if (@matchlines) { + ($width, $height) = ($matchlines[0] =~ /(\d+)x(\d+) pixels/); + + $width -= $wmDecorationWidth; + $height -= $wmDecorationHeight; + + $geometry = "${width}x$height"; + } + + @matchlines = grep(/default visual id/, @lines); + if (@matchlines) { + ($defaultVisualId) = ($matchlines[0] =~ /id:\s+(\S+)/); + + for ($i = 0; $i < @lines; $i++) { + if ($lines[$i] =~ /^\s*visual id:\s+$defaultVisualId$/) { + if (($lines[$i+1] !~ /TrueColor/) || + ($lines[$i+2] !~ /depth/) || + ($lines[$i+4] !~ /red, green, blue masks/)) + { + return; + } + last; + } + } + + return if ($i >= @lines); + + ($depth) = ($lines[$i+2] =~ /depth:\s+(\d+)/); + ($red,$green,$blue) + = ($lines[$i+4] + =~ /masks:\s+0x([0-9a-f]+), 0x([0-9a-f]+), 0x([0-9a-f]+)/); + + $red = hex($red); + $green = hex($green); + $blue = hex($blue); + + if ($red > $blue) { + $red = int(log($red) / log(2)) - int(log($green) / log(2)); + $green = int(log($green) / log(2)) - int(log($blue) / log(2)); + $blue = int(log($blue) / log(2)) + 1; + $pixelformat = "rgb$red$green$blue"; + } else { + $blue = int(log($blue) / log(2)) - int(log($green) / log(2)); + $green = int(log($green) / log(2)) - int(log($red) / log(2)); + $red = int(log($red) / log(2)) + 1; + $pixelformat = "bgr$blue$green$red"; + } + } +} + + +# +# quotedString returns a string which yields the original string when parsed +# by a shell. +# + +sub quotedString +{ + local ($in) = @_; + + $in =~ s/\'/\'\"\'\"\'/g; + + return "'$in'"; +} + + +# +# removeSlashes turns slashes into underscores for use as a file name. +# + +sub removeSlashes +{ + local ($in) = @_; + + $in =~ s|/|_|g; + + return "$in"; +} + + +# +# Usage +# + +sub Usage +{ + die("\nusage: $prog [:] [-name ] [-depth ]\n". + " [-geometry x]\n". + " [-pixelformat rgbNNN|bgrNNN]\n". + " ...\n\n". + " $prog -kill \n\n"); +} + + +# +# Kill +# + +sub Kill +{ + $opt{'-kill'} =~ s/(:\d+)\.\d+$/$1/; # e.g. turn :1.0 into :1 + + if ($opt{'-kill'} =~ /^:\d+$/) { + $pidFile = "$vncUserDir/$host$opt{'-kill'}.pid"; + } else { + if ($opt{'-kill'} !~ /^$host:/) { + die "\nCan't tell if $opt{'-kill'} is on $host\n". + "Use -kill : instead\n\n"; + } + $pidFile = "$vncUserDir/$opt{'-kill'}.pid"; + } + + if (! -r $pidFile) { + die "\nCan't find file $pidFile\n". + "You'll have to kill the Xvnc process manually\n\n"; + } + + $SIG{'HUP'} = 'IGNORE'; + chop($pid = `cat $pidFile`); + warn "Killing Xvnc process ID $pid\n"; + system("kill $pid"); + unlink $pidFile; + exit; +} + + +# +# ParseOptions takes a list of possible options and a boolean indicating +# whether the option has a value following, and sets up an associative array +# %opt of the values of the options given on the command line. It removes all +# the arguments it uses from @ARGV and returns them in @optArgs. +# + +sub ParseOptions +{ + local (@optval) = @_; + local ($opt, @opts, %valFollows, @newargs); + + while (@optval) { + $opt = shift(@optval); + push(@opts,$opt); + $valFollows{$opt} = shift(@optval); + } + + @optArgs = (); + %opt = (); + + arg: while (defined($arg = shift(@ARGV))) { + foreach $opt (@opts) { + if ($arg eq $opt) { + push(@optArgs, $arg); + if ($valFollows{$opt}) { + if (@ARGV == 0) { + &Usage(); + } + $opt{$opt} = shift(@ARGV); + push(@optArgs, $opt{$opt}); + } else { + $opt{$opt} = 1; + } + next arg; + } + } + push(@newargs,$arg); + } + + @ARGV = @newargs; +} + + +# +# Routine to make sure we're operating in a sane environment. +# + +sub SanityCheck +{ + local ($cmd); + + # + # Get the program name + # + + ($prog) = ($0 =~ m|([^/]+)$|); + + # + # Check we have all the commands we'll need on the path. + # + + cmd: + foreach $cmd ("uname","xauth","Xvnc","vncpasswd") { + for (split(/:/,$ENV{PATH})) { + if (-x "$_/$cmd") { + next cmd; + } + } + die "$prog: couldn't find \"$cmd\" on your PATH.\n"; + } + + # + # Check the HOME environment variable is set + # + + if (!defined($ENV{HOME})) { + die "$prog: The HOME environment variable is not set.\n"; + } + chdir($ENV{HOME}); + + # + # Find socket constants. 'use Socket' is a perl5-ism, so we wrap it in an + # eval, and if it fails we try 'require "sys/socket.ph"'. If this fails, + # we just guess at the values. If you find perl moaning here, just + # hard-code the values of AF_INET and SOCK_STREAM. You can find these out + # for your platform by looking in /usr/include/sys/socket.h and related + # files. + # + + chop($os = `uname`); + chop($osrev = `uname -r`); + + eval 'use Socket'; + if ($@) { + eval 'require "sys/socket.ph"'; + if ($@) { + if (($os eq "SunOS") && ($osrev !~ /^4/)) { + $AF_INET = 2; + $SOCK_STREAM = 2; + } else { + $AF_INET = 2; + $SOCK_STREAM = 1; + } + } else { + $AF_INET = &AF_INET; + $SOCK_STREAM = &SOCK_STREAM; + } + } else { + $AF_INET = &AF_INET; + $SOCK_STREAM = &SOCK_STREAM; + } +} diff --git a/unix/vncserver.man b/unix/vncserver.man new file mode 100644 index 00000000..9eb88ec0 --- /dev/null +++ b/unix/vncserver.man @@ -0,0 +1,121 @@ +.TH vncserver 1 "17 Apr 2006" "TightVNC" "Virtual Network Computing" +.SH NAME +vncserver \- start or stop a VNC server +.SH SYNOPSIS +.B vncserver +.RI [: display# ] +.RB [ \-name +.IR desktop-name ] +.RB [ \-geometry +.IR width x height ] +.RB [ \-depth +.IR depth ] +.RB [ \-pixelformat +.IR format ] +.RI [ Xvnc-options... ] +.br +.BI "vncserver \-kill :" display# +.SH DESCRIPTION +.B vncserver +is used to start a VNC (Virtual Network Computing) desktop. +.B vncserver +is a Perl script which simplifies the process of starting an Xvnc server. It +runs Xvnc with appropriate options and starts some X applications to be +displayed in the VNC desktop. + +.B vncserver +can be run with no options at all. In this case it will choose the first +available display number (usually :1), start Xvnc as that display, and run a +couple of basic applications to get you started. You can also specify the +display number, in which case it will use that number if it is available and +exit if not, eg: + +.RS +vncserver :13 +.RE + +Editing the file $HOME/.vnc/xstartup allows you to change the applications run +at startup (but note that this will not affect an existing desktop). + +.SH OPTIONS +You can get a list of options by giving \fB\-h\fP as an option to vncserver. +In addition to the options listed below, any unrecognised options will be +passed to Xvnc - see the Xvnc man page, or "Xvnc \-help" for details. + +.TP +.B \-name \fIdesktop-name\fP +Each desktop has a name which may be displayed by the viewer. It defaults to +"\fIhost\fP:\fIdisplay#\fP (\fIusername\fP)" but you can change it with this +option. It is passed in to the xstartup script via the $VNCDESKTOP environment +variable, allowing you to run a different set of applications according to the +name of the desktop. + +.TP +.B \-geometry \fIwidth\fPx\fIheight\fP +Specify the size of the desktop to be created. Default is 1024x768. + +.TP +.B \-depth \fIdepth\fP +Specify the pixel depth in bits of the desktop to be created. Default is 16, +other possible values are 8, 15 and 24 - anything else is likely to cause +strange behaviour by applications. + +.TP +.B \-pixelformat \fIformat\fP +Specify pixel format for server to use (BGRnnn or RGBnnn). The default for +depth 8 is BGR233 (meaning the most significant two bits represent blue, the +next three green, and the least significant three represent red), the default +for depth 16 is RGB565 and for depth 24 is RGB888. + +.TP +.B \-cc 3 +As an alternative to the default TrueColor visual, this allows you to run an +Xvnc server with a PseudoColor visual (i.e. one which uses a color map or +palette), which can be useful for running some old X applications which only +work on such a display. Values other than 3 (PseudoColor) and 4 (TrueColor) +for the \-cc option may result in strange behaviour, and PseudoColor desktops +must be 8 bits deep. + +.TP +.B \-kill :\fIdisplay#\fP +This kills a VNC desktop previously started with vncserver. It does this by +killing the Xvnc process, whose process ID is stored in the file +"$HOME/.vnc/\fIhost\fP:\fIdisplay#\fP.pid". It actually ignores anything +preceding a ":" in its argument. This can be useful so you can write +"vncserver \-kill $DISPLAY", for example at the end of your xstartup file after +a particular application exits. + +.SH FILES +Several VNC-related files are found in the directory $HOME/.vnc: +.TP +$HOME/.vnc/xstartup +A shell script specifying X applications to be run when a VNC desktop is +started. If it doesn't exist, vncserver will create a new one which runs a +couple of basic applications. +.TP +$HOME/.vnc/passwd +The VNC password file. +.TP +$HOME/.vnc/\fIhost\fP:\fIdisplay#\fP.log +The log file for Xvnc and applications started in xstartup. +.TP +$HOME/.vnc/\fIhost\fP:\fIdisplay#\fP.pid +Identifies the Xvnc process ID, used by the +.B \-kill +option. + +.SH SEE ALSO +.BR vncviewer (1), +.BR vncpasswd (1), +.BR vncconfig (1), +.BR Xvnc (1) +.br +http://www.tightvnc.com + +.SH AUTHOR +Tristan Richardson, RealVNC Ltd. + +VNC was originally developed by the RealVNC team while at Olivetti +Research Ltd / AT&T Laboratories Cambridge. TightVNC additions was +implemented by Constantin Kaplinsky. Many other people participated in +development, testing and support. diff --git a/unix/vncviewer/AboutDialog.h b/unix/vncviewer/AboutDialog.h new file mode 100644 index 00000000..c4f0a7c4 --- /dev/null +++ b/unix/vncviewer/AboutDialog.h @@ -0,0 +1,42 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// AboutDialog.h +// + +#ifndef __ABOUTDIALOG_H__ +#define __ABOUTDIALOG_H__ + +#include "TXMsgBox.h" +#include "parameters.h" + +#include +#define _(String) gettext (String) +#define gettext_noop(String) String +#define N_(String) gettext_noop (String) + +extern char buildtime[]; + +class AboutDialog : public TXMsgBox { +public: + AboutDialog(Display* dpy) + : TXMsgBox(dpy, aboutText, MB_OK, _("About VNC Viewer")) { + } +}; + +#endif diff --git a/unix/vncviewer/CConn.cxx b/unix/vncviewer/CConn.cxx new file mode 100644 index 00000000..eabe33a0 --- /dev/null +++ b/unix/vncviewer/CConn.cxx @@ -0,0 +1,749 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// CConn.cxx +// + +#include +#include "CConn.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "TXViewport.h" +#include "DesktopWindow.h" +#include "ServerDialog.h" +#include "PasswdDialog.h" +#include "parameters.h" + +using namespace rfb; + +static rfb::LogWriter vlog("CConn"); + +IntParameter debugDelay("DebugDelay","Milliseconds to display inverted " + "pixel data - a debugging feature", 0); + +StringParameter menuKey("MenuKey", "The key which brings up the popup menu", + "F8"); +StringParameter windowName("name", "The X window name", ""); + +CConn::CConn(Display* dpy_, int argc_, char** argv_, network::Socket* sock_, + char* vncServerName, bool reverse) + : dpy(dpy_), argc(argc_), + argv(argv_), serverHost(0), serverPort(0), sock(sock_), viewport(0), + desktop(0), desktopEventHandler(0), + currentEncoding(encodingZRLE), lastServerEncoding((unsigned int)-1), + fullColour(::fullColour), + autoSelect(::autoSelect), shared(::shared), formatChange(false), + encodingChange(false), sameMachine(false), fullScreen(::fullScreen), + ctrlDown(false), altDown(false), + menuKeysym(0), menu(dpy, this), options(dpy, this), about(dpy), info(dpy), + reverseConnection(reverse) +{ + CharArray menuKeyStr(menuKey.getData()); + menuKeysym = XStringToKeysym(menuKeyStr.buf); + + setShared(shared); + addSecType(secTypeNone); + addSecType(secTypeVncAuth); + CharArray encStr(preferredEncoding.getData()); + int encNum = encodingNum(encStr.buf); + if (encNum != -1) { + currentEncoding = encNum; + } + cp.supportsDesktopResize = true; + cp.supportsLocalCursor = useLocalCursor; + cp.customCompressLevel = customCompressLevel; + cp.compressLevel = compressLevel; + cp.noJpeg = noJpeg; + cp.qualityLevel = qualityLevel; + initMenu(); + + if (sock) { + char* name = sock->getPeerEndpoint(); + vlog.info("Accepted connection from %s", name); + if (name) free(name); + } else { + if (vncServerName) { + getHostAndPort(vncServerName, &serverHost, &serverPort); + } else { + ServerDialog dlg(dpy, &options, &about); + if (!dlg.show() || dlg.entry.getText()[0] == 0) { + exit(1); + } + getHostAndPort(dlg.entry.getText(), &serverHost, &serverPort); + } + + sock = new network::TcpSocket(serverHost, serverPort); + vlog.info("connected to host %s port %d", serverHost, serverPort); + } + + sameMachine = sock->sameMachine(); + sock->inStream().setBlockCallback(this); + setServerName(sock->getPeerEndpoint()); + setStreams(&sock->inStream(), &sock->outStream()); + initialiseProtocol(); +} + +CConn::~CConn() { + free(serverHost); + delete desktop; + delete viewport; + delete sock; +} + +// deleteWindow() is called when the user closes the desktop or menu windows. + +void CConn::deleteWindow(TXWindow* w) { + if (w == &menu) { + menu.unmap(); + } else if (w == viewport) { + exit(1); + } +} + +// handleEvent() filters all events on the desktop and menu. Most are passed +// straight through. The exception is the F8 key. When pressed on the +// desktop, it is used to bring up the menu. An F8 press or release on the +// menu is passed through as if it were on the desktop. + +void CConn::handleEvent(TXWindow* w, XEvent* ev) +{ + KeySym ks; + char str[256]; + + switch (ev->type) { + case KeyPress: + case KeyRelease: + XLookupString(&ev->xkey, str, 256, &ks, NULL); + if (ks == menuKeysym && (ev->xkey.state & (ShiftMask|ControlMask)) == 0) { + if (w == desktop && ev->type == KeyPress) { + showMenu(ev->xkey.x_root, ev->xkey.y_root); + break; + } else if (w == &menu) { + if (ev->type == KeyPress) menu.unmap(); + desktopEventHandler->handleEvent(w, ev); + break; + } + } + // drop through + + default: + if (w == desktop) desktopEventHandler->handleEvent(w, ev); + else if (w == &menu) menuEventHandler->handleEvent(w, ev); + } +} + +// blockCallback() is called when reading from the socket would block. We +// process X events until the socket is ready for reading again. + +void CConn::blockCallback() { + fd_set rfds; + do { + struct timeval tv; + struct timeval* tvp = 0; + + // Process any incoming X events + TXWindow::handleXEvents(dpy); + + // Process expired timers and get the time until the next one + int timeoutMs = Timer::checkTimeouts(); + if (timeoutMs) { + tv.tv_sec = timeoutMs / 1000; + tv.tv_usec = (timeoutMs % 1000) * 1000; + tvp = &tv; + } + + // If there are X requests pending then poll, don't wait! + if (XPending(dpy)) { + tv.tv_usec = tv.tv_sec = 0; + tvp = &tv; + } + + // Wait for X events, VNC traffic, or the next timer expiry + FD_ZERO(&rfds); + FD_SET(ConnectionNumber(dpy), &rfds); + FD_SET(sock->getFd(), &rfds); + int n = select(FD_SETSIZE, &rfds, 0, 0, tvp); + if (n < 0) throw rdr::SystemException("select",errno); + } while (!(FD_ISSET(sock->getFd(), &rfds))); +} + + +// getPasswd() is called by the CSecurity object when it needs us to read a +// password from the user. + +void CConn::getUserPasswd(char** user, char** password) +{ + CharArray passwordFileStr(passwordFile.getData()); + if (!user && passwordFileStr.buf[0]) { + FILE* fp = fopen(passwordFileStr.buf, "r"); + if (!fp) throw rfb::Exception("Opening password file failed"); + ObfuscatedPasswd obfPwd(256); + obfPwd.length = fread(obfPwd.buf, 1, obfPwd.length, fp); + fclose(fp); + PlainPasswd passwd(obfPwd); + *password = passwd.takeBuf(); + return; + } + + const char* secType = secTypeName(getCurrentCSecurity()->getType()); + const char* titlePrefix = _("VNC authentication"); + unsigned int titleLen = strlen(titlePrefix) + strlen(secType) + 4; + CharArray title(titleLen); + snprintf(title.buf, titleLen, "%s [%s]", titlePrefix, secType); + PasswdDialog dlg(dpy, title.buf, !user); + if (!dlg.show()) throw rfb::Exception("Authentication cancelled"); + if (user) + *user = strDup(dlg.userEntry.getText()); + *password = strDup(dlg.passwdEntry.getText()); +} + + +// CConnection callback methods + +// getCSecurity() gets the appropriate CSecurity object for the security +// types which we support. +CSecurity* CConn::getCSecurity(int secType) { + switch (secType) { + case secTypeNone: + return new CSecurityNone(); + case secTypeVncAuth: + return new CSecurityVncAuth(this); + default: + throw rfb::Exception("Unsupported secType?"); + } +} + +// serverInit() is called when the serverInit message has been received. At +// this point we create the desktop window and display it. We also tell the +// server the pixel format and encodings to use and request the first update. +void CConn::serverInit() { + CConnection::serverInit(); + + // If using AutoSelect with old servers, start in FullColor + // mode. See comment in autoSelectFormatAndEncoding. + if (cp.beforeVersion(3, 8) && autoSelect) { + fullColour = true; + } + + serverPF = cp.pf(); + desktop = new DesktopWindow(dpy, cp.width, cp.height, serverPF, this); + desktopEventHandler = desktop->setEventHandler(this); + desktop->addEventMask(KeyPressMask | KeyReleaseMask); + fullColourPF = desktop->getPF(); + if (!serverPF.trueColour) + fullColour = true; + recreateViewport(); + formatChange = encodingChange = true; + requestNewUpdate(); +} + +// setDesktopSize() is called when the desktop size changes (including when +// it is set initially). +void CConn::setDesktopSize(int w, int h) { + CConnection::setDesktopSize(w,h); + if (desktop) { + desktop->resize(w, h); + recreateViewport(); + } +} + +// framebufferUpdateEnd() is called at the end of an update. +// For each rectangle, the FdInStream will have timed the speed +// of the connection, allowing us to select format and encoding +// appropriately, and then request another incremental update. +void CConn::framebufferUpdateEnd() { + if (debugDelay != 0) { + XSync(dpy, False); + struct timeval tv; + tv.tv_sec = debugDelay / 1000; + tv.tv_usec = (debugDelay % 1000) * 1000; + select(0, 0, 0, 0, &tv); + std::list::iterator i; + for (i = debugRects.begin(); i != debugRects.end(); i++) { + desktop->invertRect(*i); + } + debugRects.clear(); + } + desktop->framebufferUpdateEnd(); + if (autoSelect) + autoSelectFormatAndEncoding(); + requestNewUpdate(); +} + +// The rest of the callbacks are fairly self-explanatory... + +void CConn::setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs) +{ + desktop->setColourMapEntries(firstColour, nColours, rgbs); +} + +void CConn::bell() { XBell(dpy, 0); } + +void CConn::serverCutText(const char* str, int len) { + desktop->serverCutText(str,len); +} + +// We start timing on beginRect and stop timing on endRect, to +// avoid skewing the bandwidth estimation as a result of the server +// being slow or the network having high latency +void CConn::beginRect(const Rect& r, unsigned int encoding) +{ + sock->inStream().startTiming(); + if (encoding != encodingCopyRect) { + lastServerEncoding = encoding; + } +} + +void CConn::endRect(const Rect& r, unsigned int encoding) +{ + sock->inStream().stopTiming(); + if (debugDelay != 0) { + desktop->invertRect(r); + debugRects.push_back(r); + } +} + +void CConn::fillRect(const rfb::Rect& r, rfb::Pixel p) { + desktop->fillRect(r,p); +} +void CConn::imageRect(const rfb::Rect& r, void* p) { + desktop->imageRect(r,p); +} +void CConn::copyRect(const rfb::Rect& r, int sx, int sy) { + desktop->copyRect(r,sx,sy); +} +void CConn::setCursor(int width, int height, const Point& hotspot, + void* data, void* mask) { + desktop->setCursor(width, height, hotspot, data, mask); +} + + +// Menu stuff - menuSelect() is called when the user selects a menu option. + +enum { ID_OPTIONS, ID_INFO, ID_FULLSCREEN, ID_REFRESH, ID_F8, ID_CTRLALTDEL, + ID_ABOUT, ID_DISMISS, ID_EXIT, ID_NEWCONN, ID_CTRL, ID_ALT }; + +void CConn::initMenu() { + menuEventHandler = menu.setEventHandler(this); + menu.addEventMask(KeyPressMask | KeyReleaseMask); + menu.addEntry(_("Exit viewer"), ID_EXIT); + menu.addEntry(0, 0); + menu.addEntry(_("Full screen"), ID_FULLSCREEN); + menu.check(ID_FULLSCREEN, fullScreen); + menu.addEntry(0, 0); + menu.addEntry(_("Ctrl"), ID_CTRL); + menu.addEntry(_("Alt"), ID_ALT); + CharArray menuKeyStr(menuKey.getData()); + CharArray sendMenuKey(64); + snprintf(sendMenuKey.buf, 64, _("Send %s"), menuKeyStr.buf); + menu.addEntry(sendMenuKey.buf, ID_F8); + menu.addEntry(_("Send Ctrl-Alt-Del"), ID_CTRLALTDEL); + menu.addEntry(0, 0); + menu.addEntry(_("Refresh screen"), ID_REFRESH); + menu.addEntry(0, 0); + menu.addEntry(_("New connection..."), ID_NEWCONN); + menu.addEntry(_("Options..."), ID_OPTIONS); + menu.addEntry(_("Connection info..."), ID_INFO); + menu.addEntry(_("About VNCviewer..."), ID_ABOUT); + menu.addEntry(0, 0); + menu.addEntry(_("Dismiss menu"), ID_DISMISS); + menu.toplevel(_("VNC Menu"), this); + menu.setBorderWidth(1); +} + +void CConn::showMenu(int x, int y) { + menu.check(ID_FULLSCREEN, fullScreen); + if (x + menu.width() > viewport->width()) + x = viewport->width() - menu.width(); + if (y + menu.height() > viewport->height()) + y = viewport->height() - menu.height(); + menu.move(x, y); + menu.raise(); + menu.map(); +} + +void CConn::menuSelect(long id, TXMenu* m) { + switch (id) { + case ID_NEWCONN: + { + menu.unmap(); + if (fullScreen) { + fullScreen = false; + if (viewport) recreateViewport(); + } + int pid = fork(); + if (pid < 0) { perror("fork"); exit(1); } + if (pid == 0) { + delete sock; + close(ConnectionNumber(dpy)); + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 200*1000; + select(0, 0, 0, 0, &tv); + execlp(programName, programName, 0); + perror("execlp"); exit(1); + } + break; + } + case ID_OPTIONS: + menu.unmap(); + options.show(); + break; + case ID_INFO: + { + menu.unmap(); + char pfStr[100]; + char spfStr[100]; + cp.pf().print(pfStr, 100); + serverPF.print(spfStr, 100); + int secType = getCurrentCSecurity()->getType(); + char infoText[1024]; + snprintf(infoText, sizeof(infoText), + _("Desktop name: %.80s\n" + "Host: %.80s port: %d\n" + "Size: %d x %d\n" + "Pixel format: %s\n" + "(server default %s)\n" + "Requested encoding: %s\n" + "Last used encoding: %s\n" + "Line speed estimate: %d kbit/s\n" + "Protocol version: %d.%d\n" + "Security method: %s\n"), + cp.name(), serverHost, serverPort, cp.width, cp.height, + pfStr, spfStr, encodingName(currentEncoding), + encodingName(lastServerEncoding), + sock->inStream().kbitsPerSecond(), + cp.majorVersion, cp.minorVersion, + secTypeName(secType)); + info.setText(infoText); + info.show(); + break; + } + case ID_FULLSCREEN: + menu.unmap(); + fullScreen = !fullScreen; + if (viewport) recreateViewport(); + break; + case ID_REFRESH: + menu.unmap(); + writer()->writeFramebufferUpdateRequest(Rect(0, 0, cp.width, cp.height), + false); + break; + case ID_F8: + menu.unmap(); + if (!viewOnly) { + writer()->keyEvent(menuKeysym, true); + writer()->keyEvent(menuKeysym, false); + } + break; + case ID_CTRLALTDEL: + menu.unmap(); + if (!viewOnly) { + writer()->keyEvent(XK_Control_L, true); + writer()->keyEvent(XK_Alt_L, true); + writer()->keyEvent(XK_Delete, true); + writer()->keyEvent(XK_Delete, false); + writer()->keyEvent(XK_Alt_L, false); + writer()->keyEvent(XK_Control_L, false); + } + break; + case ID_CTRL: + menu.unmap(); + if (!viewOnly) { + ctrlDown = !ctrlDown; + writer()->keyEvent(XK_Control_L, ctrlDown); + menu.check(ID_CTRL, ctrlDown); + } + break; + case ID_ALT: + menu.unmap(); + if (!viewOnly) { + altDown = !altDown; + writer()->keyEvent(XK_Alt_L, altDown); + menu.check(ID_ALT, altDown); + } + break; + case ID_ABOUT: + menu.unmap(); + about.show(); + break; + case ID_DISMISS: + menu.unmap(); + break; + case ID_EXIT: + exit(1); + break; + } +} + + +// OptionsDialogCallback. setOptions() sets the options dialog's checkboxes +// etc to reflect our flags. getOptions() sets our flags according to the +// options dialog's checkboxes. + +void CConn::setOptions() { + char digit[2] = "0"; + options.autoSelect.checked(autoSelect); + options.fullColour.checked(fullColour); + options.veryLowColour.checked(!fullColour && lowColourLevel == 0); + options.lowColour.checked(!fullColour && lowColourLevel == 1); + options.mediumColour.checked(!fullColour && lowColourLevel == 2); + options.tight.checked(currentEncoding == encodingTight); + options.zrle.checked(currentEncoding == encodingZRLE); + options.hextile.checked(currentEncoding == encodingHextile); + options.raw.checked(currentEncoding == encodingRaw); + + options.customCompressLevel.checked(customCompressLevel); + digit[0] = '0' + compressLevel; + options.compressLevel.setText(digit); + options.noJpeg.checked(!noJpeg); + digit[0] = '0' + qualityLevel; + options.qualityLevel.setText(digit); + + options.viewOnly.checked(viewOnly); + options.acceptClipboard.checked(acceptClipboard); + options.sendClipboard.checked(sendClipboard); + options.sendPrimary.checked(sendPrimary); + if (state() == RFBSTATE_NORMAL) + options.shared.disabled(true); + else + options.shared.checked(shared); + options.fullScreen.checked(fullScreen); + options.useLocalCursor.checked(useLocalCursor); + options.dotWhenNoCursor.checked(dotWhenNoCursor); +} + +void CConn::getOptions() { + autoSelect = options.autoSelect.checked(); + if (fullColour != options.fullColour.checked()) + formatChange = true; + fullColour = options.fullColour.checked(); + if (!fullColour) { + int newLowColourLevel = (options.veryLowColour.checked() ? 0 : + options.lowColour.checked() ? 1 : 2); + if (newLowColourLevel != lowColourLevel) { + lowColourLevel.setParam(newLowColourLevel); + formatChange = true; + } + } + unsigned int newEncoding = (options.tight.checked() ? encodingTight : + options.zrle.checked() ? encodingZRLE : + options.hextile.checked() ? encodingHextile : + encodingRaw); + if (newEncoding != currentEncoding) { + currentEncoding = newEncoding; + encodingChange = true; + } + + customCompressLevel.setParam(options.customCompressLevel.checked()); + if (cp.customCompressLevel != customCompressLevel) { + cp.customCompressLevel = customCompressLevel; + encodingChange = true; + } + compressLevel.setParam(options.compressLevel.getText()); + if (cp.compressLevel != compressLevel) { + cp.compressLevel = compressLevel; + encodingChange = true; + } + noJpeg.setParam(!options.noJpeg.checked()); + if (cp.noJpeg != noJpeg) { + cp.noJpeg = noJpeg; + encodingChange = true; + } + qualityLevel.setParam(options.qualityLevel.getText()); + if (cp.qualityLevel != qualityLevel) { + cp.qualityLevel = qualityLevel; + encodingChange = true; + } + + viewOnly.setParam(options.viewOnly.checked()); + acceptClipboard.setParam(options.acceptClipboard.checked()); + sendClipboard.setParam(options.sendClipboard.checked()); + sendPrimary.setParam(options.sendPrimary.checked()); + shared = options.shared.checked(); + setShared(shared); + if (fullScreen != options.fullScreen.checked()) { + fullScreen = options.fullScreen.checked(); + if (viewport) recreateViewport(); + } + useLocalCursor.setParam(options.useLocalCursor.checked()); + if (cp.supportsLocalCursor != useLocalCursor) { + cp.supportsLocalCursor = useLocalCursor; + encodingChange = true; + if (desktop) + desktop->resetLocalCursor(); + } + dotWhenNoCursor.setParam(options.dotWhenNoCursor.checked()); + checkEncodings(); +} + +void CConn::recreateViewport() +{ + TXViewport* oldViewport = viewport; + viewport = new TXViewport(dpy, cp.width, cp.height); + desktop->setViewport(viewport); + CharArray windowNameStr(windowName.getData()); + if (!windowNameStr.buf[0]) { + windowNameStr.replaceBuf(new char[256]); + snprintf(windowNameStr.buf, 256, "VNC: %.240s", cp.name()); + } + viewport->toplevel(windowNameStr.buf, this, argc, argv); + viewport->setBumpScroll(fullScreen); + XSetWindowAttributes attr; + attr.override_redirect = fullScreen; + XChangeWindowAttributes(dpy, viewport->win(), CWOverrideRedirect, &attr); + XChangeWindowAttributes(dpy, menu.win(), CWOverrideRedirect, &attr); + XChangeWindowAttributes(dpy, options.win(), CWOverrideRedirect, &attr); + XChangeWindowAttributes(dpy, about.win(), CWOverrideRedirect, &attr); + XChangeWindowAttributes(dpy, info.win(), CWOverrideRedirect, &attr); + reconfigureViewport(); + menu.setTransientFor(viewport->win()); + viewport->map(); + if (fullScreen) { + XGrabKeyboard(dpy, desktop->win(), True, GrabModeAsync, GrabModeAsync, + CurrentTime); + } else { + XUngrabKeyboard(dpy, CurrentTime); + } + if (oldViewport) delete oldViewport; +} + +void CConn::reconfigureViewport() +{ + viewport->setMaxSize(cp.width, cp.height); + if (fullScreen) { + viewport->resize(DisplayWidth(dpy,DefaultScreen(dpy)), + DisplayHeight(dpy,DefaultScreen(dpy))); + } else { + int w = cp.width; + int h = cp.height; + if (w + wmDecorationWidth >= DisplayWidth(dpy,DefaultScreen(dpy))) + w = DisplayWidth(dpy,DefaultScreen(dpy)) - wmDecorationWidth; + if (h + wmDecorationHeight >= DisplayHeight(dpy,DefaultScreen(dpy))) + h = DisplayHeight(dpy,DefaultScreen(dpy)) - wmDecorationHeight; + + int x = (DisplayWidth(dpy,DefaultScreen(dpy)) - w - wmDecorationWidth) / 2; + int y = (DisplayHeight(dpy,DefaultScreen(dpy)) - h - wmDecorationHeight)/2; + + CharArray geometryStr(geometry.getData()); + viewport->setGeometry(geometryStr.buf, x, y, w, h); + } +} + +// Note: The method below is duplicated in vncviewer/cview.cxx! + +// autoSelectFormatAndEncoding() chooses the format and encoding appropriate +// to the connection speed: +// +// Above 16Mbps (timing for at least a second), switch to hextile +// Otherwise, switch to ZRLE +// +// Above 256Kbps, use full colour mode +// +void CConn::autoSelectFormatAndEncoding() +{ + int kbitsPerSecond = sock->inStream().kbitsPerSecond(); + unsigned int newEncoding = currentEncoding; + bool newFullColour = fullColour; + unsigned int timeWaited = sock->inStream().timeWaited(); + + // Select best encoding + if (kbitsPerSecond > 16000 && timeWaited >= 10000) { + newEncoding = encodingHextile; + } else { + newEncoding = encodingZRLE; + } + + if (newEncoding != currentEncoding) { + vlog.info("Throughput %d kbit/s - changing to %s encoding", + kbitsPerSecond, encodingName(newEncoding)); + currentEncoding = newEncoding; + encodingChange = true; + } + + if (kbitsPerSecond == 0) { + return; + } + + if (cp.beforeVersion(3, 8)) { + // Xvnc from TightVNC 1.2.9 sends out FramebufferUpdates with + // cursors "asynchronously". If this happens in the middle of a + // pixel format change, the server will encode the cursor with + // the old format, but the client will try to decode it + // according to the new format. This will lead to a + // crash. Therefore, we do not allow automatic format change for + // old servers. + return; + } + + // Select best color level + newFullColour = (kbitsPerSecond > 256); + if (newFullColour != fullColour) { + vlog.info("Throughput %d kbit/s - full color is now %s", + kbitsPerSecond, + newFullColour ? "enabled" : "disabled"); + fullColour = newFullColour; + formatChange = true; + } +} + +// checkEncodings() sends a setEncodings message if one is needed. +void CConn::checkEncodings() +{ + if (encodingChange && writer()) { + vlog.info("Using %s encoding",encodingName(currentEncoding)); + writer()->writeSetEncodings(currentEncoding, true); + encodingChange = false; + } +} + +// requestNewUpdate() requests an update from the server, having set the +// format and encoding appropriately. +void CConn::requestNewUpdate() +{ + if (formatChange) { + if (fullColour) { + desktop->setPF(fullColourPF); + } else { + if (lowColourLevel == 0) + desktop->setPF(PixelFormat(8,3,0,1,1,1,1,2,1,0)); + else if (lowColourLevel == 1) + desktop->setPF(PixelFormat(8,6,0,1,3,3,3,4,2,0)); + else + desktop->setPF(PixelFormat(8,8,0,0)); + } + char str[256]; + desktop->getPF().print(str, 256); + vlog.info("Using pixel format %s",str); + cp.setPF(desktop->getPF()); + writer()->writeSetPixelFormat(cp.pf()); + } + checkEncodings(); + writer()->writeFramebufferUpdateRequest(Rect(0, 0, cp.width, cp.height), + !formatChange); + formatChange = false; +} diff --git a/unix/vncviewer/CConn.h b/unix/vncviewer/CConn.h new file mode 100644 index 00000000..a81af48c --- /dev/null +++ b/unix/vncviewer/CConn.h @@ -0,0 +1,130 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// CConn represents a client connection to a VNC server. +// + +#ifndef __CCONN_H__ +#define __CCONN_H__ + +#include +#include +#include +#include +#include + +#include "TXWindow.h" +#include "AboutDialog.h" +#include "InfoDialog.h" +#include "TXMenu.h" +#include "OptionsDialog.h" + +class TXWindow; +class TXViewport; +class DesktopWindow; +namespace network { class Socket; } + +class CConn : public rfb::CConnection, public rfb::UserPasswdGetter, + public TXDeleteWindowCallback, + public rdr::FdInStreamBlockCallback, + public TXMenuCallback , public OptionsDialogCallback, + public TXEventHandler +{ +public: + + CConn(Display* dpy_, int argc_, char** argv_, network::Socket* sock_, + char* vncServerName, bool reverse=false); + ~CConn(); + + // TXDeleteWindowCallback methods + void deleteWindow(TXWindow* w); + + // FdInStreamBlockCallback methods + void blockCallback(); + + // UserPasswdGetter methods + virtual void getUserPasswd(char** user, char** password); + + // TXMenuCallback methods + void menuSelect(long id, TXMenu* m); + + // OptionsDialogCallback methods + virtual void setOptions(); + virtual void getOptions(); + + // TXEventHandler callback method + virtual void handleEvent(TXWindow* w, XEvent* ev); + + // CConnection callback methods + rfb::CSecurity* getCSecurity(int secType); + void serverInit(); + void setDesktopSize(int w, int h); + void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs); + void bell(); + void serverCutText(const char* str, int len); + void framebufferUpdateEnd(); + void beginRect(const rfb::Rect& r, unsigned int encoding); + void endRect(const rfb::Rect& r, unsigned int encoding); + void fillRect(const rfb::Rect& r, rfb::Pixel p); + void imageRect(const rfb::Rect& r, void* p); + void copyRect(const rfb::Rect& r, int sx, int sy); + void setCursor(int width, int height, const rfb::Point& hotspot, + void* data, void* mask); + +private: + + void recreateViewport(); + void reconfigureViewport(); + void initMenu(); + void showMenu(int x, int y); + void autoSelectFormatAndEncoding(); + void checkEncodings(); + void requestNewUpdate(); + + Display* dpy; + int argc; + char** argv; + char* serverHost; + int serverPort; + network::Socket* sock; + rfb::PixelFormat serverPF; + TXViewport* viewport; + DesktopWindow* desktop; + TXEventHandler* desktopEventHandler; + rfb::PixelFormat fullColourPF; + std::list debugRects; + unsigned int currentEncoding, lastServerEncoding; + bool fullColour; + bool autoSelect; + bool shared; + bool formatChange; + bool encodingChange; + bool sameMachine; + bool fullScreen; + bool ctrlDown; + bool altDown; + KeySym menuKeysym; + TXMenu menu; + TXEventHandler* menuEventHandler; + OptionsDialog options; + AboutDialog about; + InfoDialog info; + bool reverseConnection; +}; + +#endif diff --git a/unix/vncviewer/DesktopWindow.cxx b/unix/vncviewer/DesktopWindow.cxx new file mode 100644 index 00000000..657572a4 --- /dev/null +++ b/unix/vncviewer/DesktopWindow.cxx @@ -0,0 +1,571 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// DesktopWindow.cxx +// + +#include "DesktopWindow.h" +#include "CConn.h" +#include +#include +#include +#include +#include +#include +#include "parameters.h" + +#ifndef XK_ISO_Left_Tab +#define XK_ISO_Left_Tab 0xFE20 +#endif + +static rdr::U8 reverseBits[] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, + 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, + 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, + 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, + 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, + 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, + 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, + 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, + 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, + 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, + 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, + 0x3f, 0xbf, 0x7f, 0xff +}; + +using namespace rfb; + +static rfb::LogWriter vlog("DesktopWindow"); + +DesktopWindow::DesktopWindow(Display* dpy, int w, int h, + const rfb::PixelFormat& serverPF, + CConn* cc_, TXWindow* parent) + : TXWindow(dpy, w, h, parent), cc(cc_), im(0), + cursorVisible(false), cursorAvailable(false), currentSelectionTime(0), + newSelection(0), gettingInitialSelectionTime(true), + newServerCutText(false), serverCutText_(0), + setColourMapEntriesTimer(this), viewport(0), + pointerEventTimer(this), + lastButtonMask(0) +{ + setEventHandler(this); + gc = XCreateGC(dpy, win(), 0, 0); + addEventMask(ExposureMask | ButtonPressMask | ButtonReleaseMask | + PointerMotionMask | KeyPressMask | KeyReleaseMask | + EnterWindowMask | LeaveWindowMask); + createXCursors(); + XDefineCursor(dpy, win(), dotCursor); + im = new TXImage(dpy, width(), height()); + if (!serverPF.trueColour) + im->setPF(serverPF); + XConvertSelection(dpy, sendPrimary ? XA_PRIMARY : xaCLIPBOARD, xaTIMESTAMP, + xaSELECTION_TIME, win(), CurrentTime); + memset(downKeysym, 0, 256*4); +} + +DesktopWindow::~DesktopWindow() +{ + XFreeGC(dpy, gc); + XFreeCursor(dpy, dotCursor); + XFreeCursor(dpy, noCursor); + if (localXCursor) + XFreeCursor(dpy, localXCursor); + delete im; +} + +void DesktopWindow::setViewport(TXViewport* viewport_) +{ + viewport = viewport_; + viewport->setChild(this); +} + +// Cursor stuff + +void DesktopWindow::createXCursors() +{ + static char dotSource[] = { 0x00, 0x0e, 0x0e, 0x0e, 0x00 }; + static char dotMask[] = { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }; + Pixmap source = XCreateBitmapFromData(dpy, win(), dotSource, 5, 5); + Pixmap mask = XCreateBitmapFromData(dpy, win(), dotMask, 5, 5); + XColor fg, bg; + fg.red = fg.green = fg.blue = 0; + bg.red = bg.green = bg.blue = 0xffff; + dotCursor = XCreatePixmapCursor(dpy, source, mask, &fg, &bg, 2, 2); + XFreePixmap(dpy, source); + XFreePixmap(dpy, mask); + char zero = 0; + Pixmap empty = XCreateBitmapFromData(dpy, win(), &zero, 1, 1); + noCursor = XCreatePixmapCursor(dpy, empty, empty, &fg, &bg, 0, 0); + XFreePixmap(dpy, empty); + localXCursor = 0; +} + +void DesktopWindow::setCursor(int width, int height, const Point& hotspot, + void* data, void* mask) +{ + if (!useLocalCursor) return; + + hideLocalCursor(); + + int mask_len = ((width+7)/8) * height; + + int i; + for (i = 0; i < mask_len; i++) + if (((rdr::U8*)mask)[i]) break; + + if (i == mask_len) { + if (dotWhenNoCursor) { + vlog.debug("cursor is empty - using dot"); + XDefineCursor(dpy, win(), dotCursor); + } else { + XDefineCursor(dpy, win(), noCursor); + } + cursorAvailable = false; + return; + } + + cursor.hotspot = hotspot; + + cursor.setSize(width, height); + cursor.setPF(getPF()); + cursor.imageRect(cursor.getRect(), data); + + cursorBacking.setSize(width, height); + cursorBacking.setPF(getPF()); + + delete [] cursor.mask.buf; + cursor.mask.buf = new rdr::U8[mask_len]; + memcpy(cursor.mask.buf, mask, mask_len); + + Pixel pix0, pix1; + rdr::U8Array bitmap(cursor.getBitmap(&pix0, &pix1)); + if (bitmap.buf && cursor.getRect().contains(cursor.hotspot)) { + int bytesPerRow = (cursor.width() + 7) / 8; + for (int j = 0; j < cursor.height(); j++) { + for (int i = 0; i < bytesPerRow; i++) { + bitmap.buf[j * bytesPerRow + i] + = reverseBits[bitmap.buf[j * bytesPerRow + i]]; + cursor.mask.buf[j * bytesPerRow + i] + = reverseBits[cursor.mask.buf[j * bytesPerRow + i]]; + } + } + Pixmap source = XCreateBitmapFromData(dpy, win(), (char*)bitmap.buf, + cursor.width(), cursor.height()); + Pixmap mask = XCreateBitmapFromData(dpy, win(), (char*)cursor.mask.buf, + cursor.width(), cursor.height()); + Colour rgb; + XColor fg, bg; + getPF().rgbFromPixel(pix1, im->getColourMap(), &rgb); + fg.red = rgb.r; fg.green = rgb.g; fg.blue = rgb.b; + getPF().rgbFromPixel(pix0, im->getColourMap(), &rgb); + bg.red = rgb.r; bg.green = rgb.g; bg.blue = rgb.b; + if (localXCursor) + XFreeCursor(dpy, localXCursor); + localXCursor = XCreatePixmapCursor(dpy, source, mask, &fg, &bg, + cursor.hotspot.x, cursor.hotspot.y); + XDefineCursor(dpy, win(), localXCursor); + XFreePixmap(dpy, source); + XFreePixmap(dpy, mask); + cursorAvailable = false; + return; + } + + if (!cursorAvailable) { + XDefineCursor(dpy, win(), noCursor); + cursorAvailable = true; + } + + showLocalCursor(); +} + +void DesktopWindow::resetLocalCursor() +{ + hideLocalCursor(); + XDefineCursor(dpy, win(), dotCursor); + cursorAvailable = false; +} + +void DesktopWindow::hideLocalCursor() +{ + // - Blit the cursor backing store over the cursor + if (cursorVisible) { + cursorVisible = false; + im->imageRect(cursorBackingRect, cursorBacking.data); + im->put(win(), gc, cursorBackingRect); + } +} + +void DesktopWindow::showLocalCursor() +{ + if (cursorAvailable && !cursorVisible) { + if (!getPF().equal(cursor.getPF()) || + cursor.getRect().is_empty()) { + vlog.error("attempting to render invalid local cursor"); + XDefineCursor(dpy, win(), dotCursor); + cursorAvailable = false; + return; + } + cursorVisible = true; + + rfb::Rect cursorRect = (cursor.getRect().translate(cursorPos). + translate(cursor.hotspot.negate())); + cursorBackingRect = cursorRect.intersect(im->getRect()); + im->getImage(cursorBacking.data, cursorBackingRect); + + im->maskRect(cursorRect, cursor.data, cursor.mask.buf); + im->put(win(), gc, cursorBackingRect); + } +} + +// setColourMapEntries() changes some of the entries in the colourmap. +// Unfortunately these messages are often sent one at a time, so we delay the +// settings taking effect by 100ms. This is because recalculating the internal +// translation table can be expensive. +void DesktopWindow::setColourMapEntries(int firstColour, int nColours, + rdr::U16* rgbs) +{ + im->setColourMapEntries(firstColour, nColours, rgbs); + if (!setColourMapEntriesTimer.isStarted()) + setColourMapEntriesTimer.start(100); +} + +void DesktopWindow::serverCutText(const char* str, int len) +{ + if (acceptClipboard) { + newServerCutText = true; + delete [] serverCutText_; + serverCutText_ = new char[len+1]; + memcpy(serverCutText_, str, len); + serverCutText_[len] = 0; + } +} + + +// Call XSync() at the end of an update. We do this because we'd like to +// ensure that the current update has actually been drawn by the X server +// before the next update arrives - this is necessary for copyRect to +// behave correctly. In particular, if part of the source of a copyRect is +// not actually displayed in the window, then XCopyArea results in +// GraphicsExpose events, which require us to draw from the off-screen +// image. By the time XSync returns, the GraphicsExpose events will be in +// Xlib's queue, so hopefully will be processed before the next update. +// Possibly we should process the GraphicsExpose events here explicitly? + +void DesktopWindow::framebufferUpdateEnd() +{ + XSync(dpy, False); +} + + +// invertRect() flips all the bits in every pixel in the given rectangle + +void DesktopWindow::invertRect(const Rect& r) +{ + int stride; + rdr::U8* p = im->getPixelsRW(r, &stride); + for (int y = 0; y < r.height(); y++) { + for (int x = 0; x < r.width(); x++) { + switch (getPF().bpp) { + case 8: ((rdr::U8* )p)[x+y*stride] ^= 0xff; break; + case 16: ((rdr::U16*)p)[x+y*stride] ^= 0xffff; break; + case 32: ((rdr::U32*)p)[x+y*stride] ^= 0xffffffff; break; + } + } + } + im->put(win(), gc, r); +} + + +// resize() - resize the window and the image, taking care to remove the local +// cursor first. +void DesktopWindow::resize(int w, int h) +{ + hideLocalCursor(); + TXWindow::resize(w, h); + im->resize(w, h); +} + + +bool DesktopWindow::handleTimeout(rfb::Timer* timer) +{ + if (timer == &setColourMapEntriesTimer) { + im->updateColourMap(); + im->put(win(), gc, im->getRect()); + } else if (timer == &pointerEventTimer) { + if (!viewOnly) { + cc->writer()->pointerEvent(lastPointerPos, lastButtonMask); + } + } + return false; +} + + +void DesktopWindow::handlePointerEvent(const Point& pos, int buttonMask) +{ + if (!viewOnly) { + if (pointerEventInterval == 0 || buttonMask != lastButtonMask) { + cc->writer()->pointerEvent(pos, buttonMask); + } else { + if (!pointerEventTimer.isStarted()) + pointerEventTimer.start(pointerEventInterval); + } + lastPointerPos = pos; + lastButtonMask = buttonMask; + } + // - If local cursor rendering is enabled then use it + if (cursorAvailable) { + // - Render the cursor! + if (!pos.equals(cursorPos)) { + hideLocalCursor(); + if (im->getRect().contains(pos)) { + cursorPos = pos; + showLocalCursor(); + } + } + } +} + + +// handleXEvent() handles the various X events on the window +void DesktopWindow::handleEvent(TXWindow* w, XEvent* ev) +{ + switch (ev->type) { + case GraphicsExpose: + case Expose: + im->put(win(), gc, Rect(ev->xexpose.x, ev->xexpose.y, + ev->xexpose.x + ev->xexpose.width, + ev->xexpose.y + ev->xexpose.height)); + break; + + case MotionNotify: + while (XCheckTypedWindowEvent(dpy, win(), MotionNotify, ev)); + if (viewport && viewport->bumpScrollEvent(&ev->xmotion)) break; + handlePointerEvent(Point(ev->xmotion.x, ev->xmotion.y), + (ev->xmotion.state & 0x1f00) >> 8); + break; + + case ButtonPress: + handlePointerEvent(Point(ev->xbutton.x, ev->xbutton.y), + (((ev->xbutton.state & 0x1f00) >> 8) | + (1 << (ev->xbutton.button-1)))); + break; + + case ButtonRelease: + handlePointerEvent(Point(ev->xbutton.x, ev->xbutton.y), + (((ev->xbutton.state & 0x1f00) >> 8) & + ~(1 << (ev->xbutton.button-1)))); + break; + + case KeyPress: + if (!viewOnly) { + KeySym ks; + char keyname[256]; + XLookupString(&ev->xkey, keyname, 256, &ks, NULL); + bool fakeShiftPress = false; + + // Turn ISO_Left_Tab into shifted Tab + if (ks == XK_ISO_Left_Tab) { + fakeShiftPress = !(ev->xkey.state & ShiftMask); + ks = XK_Tab; + } + + if (fakeShiftPress) + cc->writer()->keyEvent(XK_Shift_L, true); + + downKeysym[ev->xkey.keycode] = ks; + cc->writer()->keyEvent(ks, true); + + if (fakeShiftPress) + cc->writer()->keyEvent(XK_Shift_L, false); + break; + } + + case KeyRelease: + if (!viewOnly) { + if (downKeysym[ev->xkey.keycode]) { + cc->writer()->keyEvent(downKeysym[ev->xkey.keycode], false); + downKeysym[ev->xkey.keycode] = 0; + } + } + break; + + case EnterNotify: + newSelection = 0; + if (sendPrimary && !selectionOwner(XA_PRIMARY)) { + XConvertSelection(dpy, XA_PRIMARY, xaTIMESTAMP, xaSELECTION_TIME, + win(), ev->xcrossing.time); + } else if (!selectionOwner(xaCLIPBOARD)) { + XConvertSelection(dpy, xaCLIPBOARD, xaTIMESTAMP, xaSELECTION_TIME, + win(), ev->xcrossing.time); + } + break; + + case LeaveNotify: + if (serverCutText_ && newServerCutText) { + newServerCutText = false; + vlog.debug("acquiring primary and clipboard selections"); + XStoreBytes(dpy, serverCutText_, strlen(serverCutText_)); + ownSelection(XA_PRIMARY, ev->xcrossing.time); + ownSelection(xaCLIPBOARD, ev->xcrossing.time); + currentSelectionTime = ev->xcrossing.time; + } + // Release all keys - this should probably done on a FocusOut event, but + // LeaveNotify is near enough... + for (int i = 8; i < 256; i++) { + if (downKeysym[i]) { + cc->writer()->keyEvent(downKeysym[i], false); + downKeysym[i] = 0; + } + } + break; + } +} + +// selectionRequest() is called when we are the selection owner and another X +// client has requested the selection. We simply put the server's cut text +// into the requested property. TXWindow will handle the rest. +bool DesktopWindow::selectionRequest(Window requestor, + Atom selection, Atom property) +{ + XChangeProperty(dpy, requestor, property, XA_STRING, 8, + PropModeReplace, (unsigned char*)serverCutText_, + strlen(serverCutText_)); + return true; +} + + +// selectionNotify() is called when we have requested any information about a +// selection from the selection owner. Note that there are two selections, +// PRIMARY and CLIPBOARD, plus the cut buffer, and we try to use whichever is +// the most recent of the three. +// +// There are two different "targets" for which selectionNotify() is called, the +// timestamp and the actual string value of the selection. We always use the +// timestamp to decide which selection to retrieve. +// +// The first time selectionNotify() is called is when we are trying to find the +// timestamp of the selections at initialisation. This should be called first +// for PRIMARY, then we call XConvertSelection() for CLIPBOARD. The second +// time should be the result for CLIPBOARD. At this stage we've got the +// "currentSelectionTime" so we return. +// +// Subsequently selectionNotify() is called whenever the mouse enters the +// viewer window. Again, the first time it is called should be the timestamp +// for PRIMARY, and we then request the timestamp for CLIPBOARD. When +// selectionNotify() is called again with the timestamp for CLIPBOARD, we now +// know if either selection is "new" i.e. later than the previous value of +// currentSelectionTime. The last thing to check is the timestamp on the cut +// buffer. If the cut buffer is newest we send that to the server, otherwise +// if one of the selections was newer, we request the string value of that +// selection. +// +// Finally, if we get selectionNotify() called for the string value of a +// selection, we sent that to the server. +// +// As a final minor complication, when one of the selections is actually owned +// by us, we don't request the details for it. + +// TIME_LATER treats 0 as meaning a long time ago, so a==0 means a cannot be +// later than b. This is different to the usual meaning of CurrentTime. +#define TIME_LATER(a, b) ((a) != 0 && ((b) == 0 || (long)((a) - (b)) > 0)) + + +void DesktopWindow::selectionNotify(XSelectionEvent* ev, Atom type, int format, + int nitems, void* data) +{ + if (ev->requestor != win()) + return; + + if (ev->target == xaTIMESTAMP) { + if (ev->property == xaSELECTION_TIME) { + if (data && format == 32 && nitems == 1) { + Time t = *(rdr::U32 *)data; + vlog.debug("selection (%d) time is %d, later %d", + ev->selection, t, TIME_LATER(t, currentSelectionTime)); + if (TIME_LATER(t, currentSelectionTime)) { + currentSelectionTime = t; + newSelection = ev->selection; + } + } + } else { + vlog.debug("no selection (%d)",ev->selection); + } + + if (ev->selection == XA_PRIMARY) { + if (!selectionOwner(xaCLIPBOARD)) { + XConvertSelection(dpy, xaCLIPBOARD, xaTIMESTAMP, xaSELECTION_TIME, + win(), ev->time); + return; + } + } else if (ev->selection != xaCLIPBOARD) { + vlog.error("unknown selection %d",ev->selection); + return; + } + + if (gettingInitialSelectionTime) { + gettingInitialSelectionTime = false; + return; + } + + if (!sendClipboard) return; + if (sendPrimary) { + vlog.debug("cut buffer time is %d, later %d", cutBufferTime, + TIME_LATER(cutBufferTime, currentSelectionTime)); + if (TIME_LATER(cutBufferTime, currentSelectionTime)) { + currentSelectionTime = cutBufferTime; + int len; + char* str = XFetchBytes(dpy, &len); + if (str) { + if (!viewOnly) { + vlog.debug("sending cut buffer to server"); + cc->writer()->clientCutText(str, len); + } + XFree(str); + return; + } + } + } + if (newSelection) { + XConvertSelection(dpy, newSelection, XA_STRING, xaSELECTION_STRING, + win(), CurrentTime); + } + + } else if (ev->target == XA_STRING) { + if (!sendClipboard) return; + if (ev->property == xaSELECTION_STRING) { + if (data && format == 8) { + if (!viewOnly) { + vlog.debug("sending %s selection to server", + ev->selection == XA_PRIMARY ? "primary" : + ev->selection == xaCLIPBOARD ? "clipboard" : "unknown" ); + cc->writer()->clientCutText((char*)data, nitems); + } + } + } + } +} diff --git a/unix/vncviewer/DesktopWindow.h b/unix/vncviewer/DesktopWindow.h new file mode 100644 index 00000000..a1af7504 --- /dev/null +++ b/unix/vncviewer/DesktopWindow.h @@ -0,0 +1,129 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// DesktopWindow is a TXWindow representing a VNC desktop. +// + +#ifndef __DESKTOPWINDOW_H__ +#define __DESKTOPWINDOW_H__ + +#include +#include +#include +#include "TXWindow.h" +#include "TXViewport.h" +#include "TXImage.h" + +class CConn; + +class DesktopWindow : public TXWindow, public TXEventHandler, + public rfb::Timer::Callback { +public: + + DesktopWindow(Display* dpy, int w, int h, + const rfb::PixelFormat& serverPF, CConn* cc_, + TXWindow* parent=0); + ~DesktopWindow(); + + void setViewport(TXViewport* viewport); + + // getPF() and setPF() get and set the TXImage's pixel format + const rfb::PixelFormat& getPF() { return im->getPF(); } + void setPF(const rfb::PixelFormat& pf) { im->setPF(pf); } + + // setCursor() sets the shape of the local cursor + void setCursor(int width, int height, const rfb::Point& hotspot, + void* data, void* mask); + + // resetLocalCursor() stops the rendering of the local cursor + void resetLocalCursor(); + + // Methods forwarded from CConn + void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs); + void serverCutText(const char* str, int len); + void framebufferUpdateEnd(); + + void fillRect(const rfb::Rect& r, rfb::Pixel pix) { + if (r.overlaps(cursorBackingRect)) hideLocalCursor(); + im->fillRect(r, pix); + im->put(win(), gc, r); + showLocalCursor(); + } + void imageRect(const rfb::Rect& r, void* pixels) { + if (r.overlaps(cursorBackingRect)) hideLocalCursor(); + im->imageRect(r, pixels); + im->put(win(), gc, r); + showLocalCursor(); + } + void copyRect(const rfb::Rect& r, int srcX, int srcY) { + if (r.overlaps(cursorBackingRect) || + cursorBackingRect.overlaps(rfb::Rect(srcX, srcY, + srcX+r.width(), srcY+r.height()))) + hideLocalCursor(); + if (im->usingShm()) + XSync(dpy, False); + im->copyRect(r, rfb::Point(r.tl.x-srcX, r.tl.y-srcY)); + XCopyArea(dpy, win(), win(), gc, srcX, srcY, + r.width(), r.height(), r.tl.x, r.tl.y); + showLocalCursor(); + } + void invertRect(const rfb::Rect& r); + + // TXWindow methods + virtual void resize(int w, int h); + virtual bool selectionRequest(Window requestor, + Atom selection, Atom property); + virtual void selectionNotify(XSelectionEvent* ev, Atom type, int format, + int nitems, void* data); + virtual void handleEvent(TXWindow* w, XEvent* ev); + +private: + + void createXCursors(); + void hideLocalCursor(); + void showLocalCursor(); + bool handleTimeout(rfb::Timer* timer); + void handlePointerEvent(const rfb::Point& pos, int buttonMask); + + CConn* cc; + TXImage* im; + GC gc; + ::Cursor dotCursor, noCursor, localXCursor; + + rfb::Cursor cursor; + bool cursorVisible; // Is cursor currently rendered? + bool cursorAvailable; // Is cursor available for rendering? + rfb::Point cursorPos; + rfb::ManagedPixelBuffer cursorBacking; + rfb::Rect cursorBackingRect; + + Time currentSelectionTime; + Atom newSelection; + bool gettingInitialSelectionTime; + bool newServerCutText; + char* serverCutText_; + + rfb::Timer setColourMapEntriesTimer; + TXViewport* viewport; + rfb::Timer pointerEventTimer; + rfb::Point lastPointerPos; + int lastButtonMask; + rdr::U32 downKeysym[256]; +}; + +#endif diff --git a/unix/vncviewer/InfoDialog.h b/unix/vncviewer/InfoDialog.h new file mode 100644 index 00000000..a95f57be --- /dev/null +++ b/unix/vncviewer/InfoDialog.h @@ -0,0 +1,60 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// InfoDialog.h +// + +#ifndef __INFODIALOG_H__ +#define __INFODIALOG_H__ + +#include "TXDialog.h" +#include "TXLabel.h" +#include "TXButton.h" + +extern char buildtime[]; + +class InfoDialog : public TXDialog, public TXButtonCallback { +public: + InfoDialog(Display* dpy) + : TXDialog(dpy, 1, 1, _("VNC connection info")), + infoLabel(dpy, "", this, 1, 1, TXLabel::left), + okButton(dpy, "OK", this, this, 60) + { + infoLabel.xPad = 8; + infoLabel.move(0, yPad*4); + setBorderWidth(1); + } + + void setText(char* infoText) { + infoLabel.setText(infoText); + resize(infoLabel.width(), + infoLabel.height() + okButton.height() + yPad*12); + + okButton.move((width() - okButton.width()) / 2, + height() - yPad*4 - okButton.height()); + } + + virtual void buttonActivate(TXButton* b) { + unmap(); + } + + TXLabel infoLabel; + TXButton okButton; +}; + +#endif diff --git a/unix/vncviewer/Makefile.in b/unix/vncviewer/Makefile.in new file mode 100644 index 00000000..782b6804 --- /dev/null +++ b/unix/vncviewer/Makefile.in @@ -0,0 +1,30 @@ + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +prefix = @prefix@ +datadir = @datadir@ +localedir = $(datadir)/locale + +SRCS = DesktopWindow.cxx CConn.cxx vncviewer.cxx + +OBJS = $(SRCS:.cxx=.o) + +program = vncviewer + +DEP_LIBS = ../tx/libtx.a ../rfb/librfb.a ../network/libnetwork.a \ + ../rdr/librdr.a + +EXTRA_LIBS = @ZLIB_LIB@ @JPEG_LIB@ @X_PRE_LIBS@ @X_LIBS@ -lXext -lX11 @X_EXTRA_LIBS@ @LIBINTL@ + +DIR_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" -I$(top_srcdir) -I$(top_srcdir)/tx -I$(top_srcdir)/intl @X_CFLAGS@ # X_CFLAGS are really CPPFLAGS + +all:: $(program) + +$(program): $(OBJS) buildtime.o $(DEP_LIBS) + rm -f $(program) + $(CXXLD) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJS) buildtime.o $(DEP_LIBS) $(LIBS) $(EXTRA_LIBS) + +buildtime.o: $(OBJS) $(DEP_LIBS) + +# followed by boilerplate.mk diff --git a/unix/vncviewer/OptionsDialog.h b/unix/vncviewer/OptionsDialog.h new file mode 100644 index 00000000..68ce8d6a --- /dev/null +++ b/unix/vncviewer/OptionsDialog.h @@ -0,0 +1,213 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// OptionsDialog.h +// + +#ifndef __OPTIONSDIALOG_H__ +#define __OPTIONSDIALOG_H__ + +#include "TXDialog.h" +#include "TXLabel.h" +#include "TXEntry.h" +#include "TXButton.h" +#include "TXCheckbox.h" +#include "parameters.h" + +class OptionsDialogCallback { +public: + virtual void setOptions() = 0; + virtual void getOptions() = 0; +}; + +class OptionsDialog : public TXDialog, public TXButtonCallback, + public TXCheckboxCallback, public TXEntryCallback { +public: + OptionsDialog(Display* dpy, OptionsDialogCallback* cb_) + : TXDialog(dpy, 400, 450, _("VNC Viewer: Connection Options")), cb(cb_), + formatAndEnc(dpy, _("Encoding and Color Level:"), this), + inputs(dpy, _("Inputs:"), this), + misc(dpy, _("Misc:"), this), + autoSelect(dpy, _("Auto select"), this, false, this), + fullColour(dpy, _("Full (all available colors)"), this, true, this), + mediumColour(dpy, _("Medium (256 colors)"), this, true, this), + lowColour(dpy, _("Low (64 colors)"), this, true, this), + veryLowColour(dpy, _("Very low (8 colors)"), this, true, this), + tight(dpy, "Tight", this, true, this), + zrle(dpy, "ZRLE", this, true, this), + hextile(dpy, "Hextile", this, true, this), + raw(dpy, "Raw", this, true, this), + customCompressLevel(dpy, _("Custom compression level:"), this, false, this), + compressLevel(dpy, this, this, false, 30), + compressLevelLabel(dpy, _("level (1=fast, 9=best)"), this), + noJpeg(dpy, _("Allow JPEG compression:"), this, false, this), + qualityLevel(dpy, this, this, false, 30), + qualityLevelLabel(dpy, _("quality (1=poor, 9=best)"), this), + viewOnly(dpy, _("View only (ignore mouse & keyboard)"), this, false, this), + acceptClipboard(dpy, _("Accept clipboard from server"), this, false, this), + sendClipboard(dpy, _("Send clipboard to server"), this, false, this), + sendPrimary(dpy, _("Send primary selection & cut buffer as clipboard"), + this, false, this), + shared(dpy, _("Shared (don't disconnect other viewers)"), this, false,this), + fullScreen(dpy, _("Full-screen mode"), this, false, this), + useLocalCursor(dpy, _("Render cursor locally"), this, false, this), + dotWhenNoCursor(dpy, _("Show dot when no cursor"), this, false, this), + okButton(dpy, _("OK"), this, this, 60), + cancelButton(dpy, _("Cancel"), this, this, 60) + { + int y = yPad; + formatAndEnc.move(xPad, y); + y += formatAndEnc.height(); + autoSelect.move(xPad, y); + int x2 = xPad + autoSelect.width() + xPad*5; + y += autoSelect.height(); + tight.move(xPad, y); + fullColour.move(x2, y); + y += tight.height(); + zrle.move(xPad, y); + mediumColour.move(x2, y); + y += zrle.height(); + hextile.move(xPad, y); + lowColour.move(x2, y); + y += hextile.height(); + raw.move(xPad, y); + veryLowColour.move(x2, y); + y += raw.height() + yPad*2; + + customCompressLevel.move(xPad, y); + y += customCompressLevel.height(); + compressLevel.move(xPad*10, y); + compressLevelLabel.move(xPad*20, y); + y += compressLevel.height(); + + noJpeg.move(xPad, y); + y += noJpeg.height(); + qualityLevel.move(xPad*10, y); + qualityLevelLabel.move(xPad*20, y); + y += qualityLevel.height(); + + y += yPad*4; + inputs.move(xPad, y); + y += inputs.height(); + viewOnly.move(xPad, y); + y += viewOnly.height(); + acceptClipboard.move(xPad, y); + y += acceptClipboard.height(); + sendClipboard.move(xPad, y); + y += sendClipboard.height(); + sendPrimary.move(xPad, y); + y += sendPrimary.height(); + + y += yPad*4; + misc.move(xPad, y); + y += misc.height(); + shared.move(xPad, y); + y += shared.height(); + fullScreen.move(xPad, y); + y += fullScreen.height(); + useLocalCursor.move(xPad, y); + y += useLocalCursor.height(); + dotWhenNoCursor.move(xPad, y); + y += dotWhenNoCursor.height(); + + okButton.move(width() - xPad*12 - cancelButton.width() - okButton.width(), + height() - yPad*4 - okButton.height()); + cancelButton.move(width() - xPad*6 - cancelButton.width(), + height() - yPad*4 - cancelButton.height()); + setBorderWidth(1); + } + + virtual void initDialog() { + if (cb) cb->setOptions(); + tight.disabled(autoSelect.checked()); + zrle.disabled(autoSelect.checked()); + hextile.disabled(autoSelect.checked()); + raw.disabled(autoSelect.checked()); + fullColour.disabled(autoSelect.checked()); + mediumColour.disabled(autoSelect.checked()); + lowColour.disabled(autoSelect.checked()); + veryLowColour.disabled(autoSelect.checked()); + sendPrimary.disabled(!sendClipboard.checked()); + dotWhenNoCursor.disabled(!useLocalCursor.checked()); + compressLevel.disabled(!customCompressLevel.checked()); + qualityLevel.disabled(!noJpeg.checked()); + } + + virtual void takeFocus(Time time) { + //XSetInputFocus(dpy, entry.win, RevertToParent, time); + } + + virtual void buttonActivate(TXButton* b) { + if (b == &okButton) { + if (cb) cb->getOptions(); + unmap(); + } else if (b == &cancelButton) { + unmap(); + } + } + + virtual void checkboxSelect(TXCheckbox* checkbox) { + if (checkbox == &autoSelect) { + tight.disabled(autoSelect.checked()); + zrle.disabled(autoSelect.checked()); + hextile.disabled(autoSelect.checked()); + raw.disabled(autoSelect.checked()); + fullColour.disabled(autoSelect.checked()); + mediumColour.disabled(autoSelect.checked()); + lowColour.disabled(autoSelect.checked()); + veryLowColour.disabled(autoSelect.checked()); + } else if (checkbox == &fullColour || checkbox == &mediumColour || + checkbox == &lowColour || checkbox == &veryLowColour) { + fullColour.checked(checkbox == &fullColour); + mediumColour.checked(checkbox == &mediumColour); + lowColour.checked(checkbox == &lowColour); + veryLowColour.checked(checkbox == &veryLowColour); + } else if (checkbox == &tight || checkbox == &zrle || checkbox == &hextile || checkbox == &raw) { + tight.checked(checkbox == &tight); + zrle.checked(checkbox == &zrle); + hextile.checked(checkbox == &hextile); + raw.checked(checkbox == &raw); + } else if (checkbox == &sendClipboard) { + sendPrimary.disabled(!sendClipboard.checked()); + } else if (checkbox == &useLocalCursor) { + dotWhenNoCursor.disabled(!useLocalCursor.checked()); + } else if (checkbox == &customCompressLevel) { + compressLevel.disabled(!customCompressLevel.checked()); + } else if (checkbox == &noJpeg) { + qualityLevel.disabled(!noJpeg.checked()); + } + } + + virtual void entryCallback(TXEntry* e, Detail detail, Time time) { + } + + OptionsDialogCallback* cb; + TXLabel formatAndEnc, inputs, misc; + TXCheckbox autoSelect; + TXCheckbox fullColour, mediumColour, lowColour, veryLowColour; + TXCheckbox tight, zrle, hextile, raw; + + TXCheckbox customCompressLevel; TXEntry compressLevel; TXLabel compressLevelLabel; + TXCheckbox noJpeg; TXEntry qualityLevel; TXLabel qualityLevelLabel; + + TXCheckbox viewOnly, acceptClipboard, sendClipboard, sendPrimary; + TXCheckbox shared, fullScreen, useLocalCursor, dotWhenNoCursor; + TXButton okButton, cancelButton; +}; + +#endif diff --git a/unix/vncviewer/PasswdDialog.h b/unix/vncviewer/PasswdDialog.h new file mode 100644 index 00000000..7b62b8e1 --- /dev/null +++ b/unix/vncviewer/PasswdDialog.h @@ -0,0 +1,72 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// PasswdDialog.h +// + +#ifndef __PASSWDDIALOG_H__ +#define __PASSWDDIALOG_H__ + +#include "TXDialog.h" +#include "TXLabel.h" +#include "TXEntry.h" + +class PasswdDialog : public TXDialog, public TXEntryCallback { +public: + PasswdDialog(Display* dpy, const char* title, bool userDisabled) + : TXDialog(dpy, 320, 100, title, true), + userLabel(dpy, _("Username:"), this, 120), + userEntry(dpy, this, this, false, 180), + passwdLabel(dpy, _("Password:"), this, 120), + passwdEntry(dpy, this, this, true, 180) + { + userLabel.move(0, 20); + userEntry.move(userLabel.width(), 18); + userEntry.disabled(userDisabled); + passwdLabel.move(0, 60); + passwdEntry.move(passwdLabel.width(), 58); + } + + void takeFocus(Time time) { + if (!userEntry.disabled()) + XSetInputFocus(dpy, userEntry.win(), RevertToParent, time); + else + XSetInputFocus(dpy, passwdEntry.win(), RevertToParent, time); + } + + void entryCallback(TXEntry* e, Detail detail, Time time) { + if (e == &userEntry) { + if (detail == ENTER || detail == NEXT_FOCUS || detail == PREV_FOCUS) + XSetInputFocus(dpy, passwdEntry.win(), RevertToParent, time); + } else if (e == &passwdEntry) { + if (detail == ENTER) { + ok = true; + done = true; + } else if (detail == NEXT_FOCUS || detail == PREV_FOCUS) { + XSetInputFocus(dpy, userEntry.win(), RevertToParent, time); + } + } + } + + TXLabel userLabel; + TXEntry userEntry; + TXLabel passwdLabel; + TXEntry passwdEntry; +}; + +#endif diff --git a/unix/vncviewer/ServerDialog.h b/unix/vncviewer/ServerDialog.h new file mode 100644 index 00000000..f6980dc7 --- /dev/null +++ b/unix/vncviewer/ServerDialog.h @@ -0,0 +1,91 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// ServerDialog.h +// + +#ifndef __SERVERDIALOG_H__ +#define __SERVERDIALOG_H__ + +#include "TXDialog.h" +#include "TXLabel.h" +#include "TXEntry.h" +#include "TXButton.h" +#include "OptionsDialog.h" +#include "AboutDialog.h" + +class ServerDialog : public TXDialog, public TXEntryCallback, + public TXButtonCallback { +public: + ServerDialog(Display* dpy, OptionsDialog* options_, AboutDialog* about_) + : TXDialog(dpy, 355, 120, _("VNC Viewer: Connection Details"), true), + label(dpy, _("VNC server:"), this, 100), + entry(dpy, this, this, false, 180), + aboutButton(dpy, _("About..."), this, this, 70), + optionsButton(dpy, _("Options..."), this, this, 70), + okButton(dpy, _("OK"), this, this, 70), + cancelButton(dpy, _("Cancel"), this, this, 70), + options(options_), about(about_) + { + label.move(0, 30); + entry.move(label.width(), 28); + int x = width(); + int y = height() - yPad*4 - cancelButton.height(); + x -= cancelButton.width() + xPad*4; + cancelButton.move(x, y); + x -= okButton.width() + xPad*4; + okButton.move(x, y); + x -= optionsButton.width() + xPad*4; + optionsButton.move(x, y); + x -= aboutButton.width() + xPad*4; + aboutButton.move(x, y); + } + + virtual void takeFocus(Time time) { + XSetInputFocus(dpy, entry.win(), RevertToParent, time); + } + + virtual void entryCallback(TXEntry* e, Detail detail, Time time) { + if (detail == ENTER) { + ok = true; + done = true; + } + } + + virtual void buttonActivate(TXButton* b) { + if (b == &okButton) { + ok = true; + done = true; + } else if (b == &cancelButton) { + ok = false; + done = true; + } else if (b == &optionsButton) { + options->show(); + } else if (b == &aboutButton) { + about->show(); + } + } + + TXLabel label; + TXEntry entry; + TXButton aboutButton, optionsButton, okButton, cancelButton; + OptionsDialog* options; + AboutDialog* about; +}; + +#endif diff --git a/unix/vncviewer/buildtime.c b/unix/vncviewer/buildtime.c new file mode 100644 index 00000000..3f4c3690 --- /dev/null +++ b/unix/vncviewer/buildtime.c @@ -0,0 +1,18 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +char buildtime[] = __DATE__ " " __TIME__; diff --git a/unix/vncviewer/parameters.h b/unix/vncviewer/parameters.h new file mode 100644 index 00000000..6505aa8a --- /dev/null +++ b/unix/vncviewer/parameters.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#ifndef __PARAMETERS_H__ +#define __PARAMETERS_H__ + +#include + +extern rfb::IntParameter pointerEventInterval; +extern rfb::IntParameter wmDecorationWidth; +extern rfb::IntParameter wmDecorationHeight; +extern rfb::StringParameter passwordFile; +extern rfb::BoolParameter useLocalCursor; +extern rfb::BoolParameter dotWhenNoCursor; +extern rfb::BoolParameter autoSelect; +extern rfb::BoolParameter fullColour; +extern rfb::IntParameter lowColourLevel; +extern rfb::StringParameter preferredEncoding; +extern rfb::BoolParameter viewOnly; +extern rfb::BoolParameter shared; +extern rfb::BoolParameter acceptClipboard; +extern rfb::BoolParameter sendClipboard; +extern rfb::BoolParameter sendPrimary; +extern rfb::BoolParameter fullScreen; +extern rfb::StringParameter geometry; +extern rfb::BoolParameter customCompressLevel; +extern rfb::IntParameter compressLevel; +extern rfb::BoolParameter noJpeg; +extern rfb::IntParameter qualityLevel; + +extern char aboutText[]; +extern char* programName; + +#endif diff --git a/unix/vncviewer/vncviewer.cxx b/unix/vncviewer/vncviewer.cxx new file mode 100644 index 00000000..e9c9ac4c --- /dev/null +++ b/unix/vncviewer/vncviewer.cxx @@ -0,0 +1,396 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// All-new VNC viewer for X. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "TXWindow.h" +#include "TXMsgBox.h" +#include "CConn.h" + +#include +#define _(String) gettext (String) +#define gettext_noop(String) String +#define N_(String) gettext_noop (String) + +rfb::LogWriter vlog("main"); + +using namespace network; +using namespace rfb; +using namespace std; + +IntParameter pointerEventInterval("PointerEventInterval", + "Time in milliseconds to rate-limit" + " successive pointer events", 0); +IntParameter wmDecorationWidth("WMDecorationWidth", "Width of window manager " + "decoration around a window", 6); +IntParameter wmDecorationHeight("WMDecorationHeight", "Height of window " + "manager decoration around a window", 24); +StringParameter passwordFile("PasswordFile", + "Password file for VNC authentication", ""); +AliasParameter rfbauth("passwd", "Alias for PasswordFile", &passwordFile); + +BoolParameter useLocalCursor("UseLocalCursor", + "Render the mouse cursor locally", true); +BoolParameter dotWhenNoCursor("DotWhenNoCursor", + "Show the dot cursor when the server sends an " + "invisible cursor", true); +BoolParameter autoSelect("AutoSelect", + "Auto select pixel format and encoding. " + "Default if PreferredEncoding and FullColor are not specified.", + true); +BoolParameter fullColour("FullColor", + "Use full color", true); +AliasParameter fullColourAlias("FullColour", "Alias for FullColor", &fullColour); +IntParameter lowColourLevel("LowColorLevel", + "Color level to use on slow connections. " + "0 = Very Low (8 colors), 1 = Low (64 colors), " + "2 = Medium (256 colors)", 2); +AliasParameter lowColourLevelAlias("LowColourLevel", "Alias for LowColorLevel", &lowColourLevel); +StringParameter preferredEncoding("PreferredEncoding", + "Preferred encoding to use (Tight, ZRLE, Hextile or" + " Raw)", "Tight"); +BoolParameter fullScreen("FullScreen", "Full screen mode", false); +BoolParameter viewOnly("ViewOnly", + "Don't send any mouse or keyboard events to the server", + false); +BoolParameter shared("Shared", + "Don't disconnect other viewers upon connection - " + "share the desktop instead", + false); +BoolParameter acceptClipboard("AcceptClipboard", + "Accept clipboard changes from the server", + true); +BoolParameter sendClipboard("SendClipboard", + "Send clipboard changes to the server", true); +BoolParameter sendPrimary("SendPrimary", + "Send the primary selection and cut buffer to the " + "server as well as the clipboard selection", + true); + +BoolParameter listenMode("listen", "Listen for connections from VNC servers", + false); +StringParameter geometry("geometry", "X geometry specification", ""); +StringParameter displayname("display", "The X display", ""); + +StringParameter via("via", "Gateway to tunnel via", ""); + +BoolParameter customCompressLevel("CustomCompressLevel", + "Use custom compression level. " + "Default if CompressLevel is specified.", false); + +IntParameter compressLevel("CompressLevel", + "Use specified compression level" + "0 = Low, 9 = High", + 6); + +BoolParameter noJpeg("NoJPEG", + "Disable lossy JPEG compression in Tight encoding.", + false); + +IntParameter qualityLevel("QualityLevel", + "JPEG quality level. " + "0 = Low, 9 = High", + 6); + +char aboutText[1024]; +char* programName; +extern char buildtime[]; + +static void CleanupSignalHandler(int sig) +{ + // CleanupSignalHandler allows C++ object cleanup to happen because it calls + // exit() rather than the default which is to abort. + vlog.info("CleanupSignalHandler called"); + exit(1); +} + +// XLoginIconifier is a class which iconifies the XDM login window when it has +// grabbed the keyboard, thus releasing the grab, allowing the viewer to use +// the keyboard. It remaps the xlogin window on exit. +class XLoginIconifier { +public: + Display* dpy; + Window xlogin; + XLoginIconifier() : dpy(0), xlogin(0) {} + void iconify(Display* dpy_) { + dpy = dpy_; + if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), False, GrabModeSync, + GrabModeSync, CurrentTime) == GrabSuccess) { + XUngrabKeyboard(dpy, CurrentTime); + } else { + xlogin = TXWindow::windowWithName(dpy, DefaultRootWindow(dpy), "xlogin"); + if (xlogin) { + XIconifyWindow(dpy, xlogin, DefaultScreen(dpy)); + XSync(dpy, False); + } + } + } + ~XLoginIconifier() { + if (xlogin) { + fprintf(stderr,"~XLoginIconifier remapping xlogin\n"); + XMapWindow(dpy, xlogin); + XFlush(dpy); + sleep(1); + } + } +}; + +static XLoginIconifier xloginIconifier; + +static void usage() +{ + fprintf(stderr, + "\nusage: %s [parameters] [host:displayNum] [parameters]\n" + " %s [parameters] -listen [port] [parameters]\n", + programName,programName); + fprintf(stderr,"\n" + "Parameters can be turned on with - or off with -=0\n" + "Parameters which take a value can be specified as " + "- \n" + "Other valid forms are = -= " + "--=\n" + "Parameter names are case-insensitive. The parameters are:\n\n"); + Configuration::listParams(79, 14); + exit(1); +} + +/* Tunnelling support. */ +static void +interpretViaParam (char **gatewayHost, char **remoteHost, + int *remotePort, char **vncServerName, + int localPort) +{ + const int SERVER_PORT_OFFSET = 5900; + char *pos = strchr (*vncServerName, ':'); + if (pos == NULL) + *remotePort = SERVER_PORT_OFFSET; + else { + int portOffset = SERVER_PORT_OFFSET; + size_t len; + *pos++ = '\0'; + len = strlen (pos); + if (*pos == ':') { + /* Two colons is an absolute port number, not an offset. */ + pos++; + len--; + portOffset = 0; + } + if (!len || strspn (pos, "-0123456789") != len ) + usage (); + *remotePort = atoi (pos) + portOffset; + } + + if (**vncServerName != '\0') + *remoteHost = *vncServerName; + + *gatewayHost = strDup (via.getValueStr ()); + *vncServerName = new char[50]; + sprintf (*vncServerName, "localhost::%d", localPort); +} + +#ifndef HAVE_SETENV +int +setenv(const char *envname, const char * envval, int overwrite) +{ + if (envname && envval) { + char * envp = NULL; + envp = (char*)malloc(strlen(envname) + strlen(envval) + 2); + if (envp) { + // The putenv API guarantees memory leaks when + // changing environment variables repeatedly. + sprintf(envp, "%s=%s", envname, envval); + + // Cannot free envp + putenv(envp); + return(0); + } + } + return(-1); +} +#endif + +static void +createTunnel (const char *gatewayHost, const char *remoteHost, + int remotePort, int localPort) +{ + char *cmd = getenv ("VNC_VIA_CMD"); + char *percent; + char lport[10], rport[10]; + sprintf (lport, "%d", localPort); + sprintf (rport, "%d", remotePort); + setenv ("G", gatewayHost, 1); + setenv ("H", remoteHost, 1); + setenv ("R", rport, 1); + setenv ("L", lport, 1); + if (!cmd) + cmd = "/usr/bin/ssh -f -L \"$L\":\"$H\":\"$R\" \"$G\" sleep 20"; + /* Compatibility with TightVNC's method. */ + while ((percent = strchr (cmd, '%')) != NULL) + *percent = '$'; + system (cmd); +} + +int main(int argc, char** argv) +{ + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + snprintf(aboutText, sizeof(aboutText), + _("TightVNC viewer for X version 1.5 - built %s\n" + "Copyright (C) 2002-2005 RealVNC Ltd.\n" + "Copyright (C) 2000-2004 Constantin Kaplinsky\n" + "Copyright (C) 2004-2005 Peter Astrand, Cendio AB\n" + "See http://www.tightvnc.com for information on TightVNC."), + buildtime); + fprintf(stderr,"\n%s\n", aboutText); + + bind_textdomain_codeset(PACKAGE, "iso-8859-1"); + + rfb::initStdIOLoggers(); + rfb::LogWriter::setLogParams("*:stderr:30"); + + signal(SIGHUP, CleanupSignalHandler); + signal(SIGINT, CleanupSignalHandler); + signal(SIGTERM, CleanupSignalHandler); + + programName = argv[0]; + char* vncServerName = 0; + Display* dpy = 0; + + for (int i = 1; i < argc; i++) { + if (Configuration::setParam(argv[i])) + continue; + + if (argv[i][0] == '-') { + if (i+1 < argc) { + if (Configuration::setParam(&argv[i][1], argv[i+1])) { + i++; + continue; + } + } + usage(); + } + + vncServerName = argv[i]; + } + + // Create .vnc in the user's home directory if it doesn't already exist + char* homeDir = getenv("HOME"); + if (homeDir) { + CharArray vncDir(strlen(homeDir)+6); + sprintf(vncDir.buf, "%s/.vnc", homeDir); + int result = mkdir(vncDir.buf, 0755); + if (result == -1 && errno != EEXIST) + vlog.error("Could not create .vnc directory: %s.", strerror(errno)); + } else + vlog.error("Could not create .vnc directory: environment variable $HOME not set."); + + if (!::autoSelect.hasBeenSet()) { + // Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used + ::autoSelect.setParam(!::preferredEncoding.hasBeenSet() + && !::fullColour.hasBeenSet() + && !::fullColourAlias.hasBeenSet()); + } + if (!::customCompressLevel.hasBeenSet()) { + // Default to CustomCompressLevel=1 if CompressLevel is used. + ::customCompressLevel.setParam(::compressLevel.hasBeenSet()); + } + + try { + /* Tunnelling support. */ + if (strlen (via.getValueStr ()) > 0) { + char *gatewayHost = ""; + char *remoteHost = "localhost"; + int localPort = findFreeTcpPort (); + int remotePort; + if (!vncServerName) + usage(); + interpretViaParam (&gatewayHost, &remoteHost, &remotePort, + &vncServerName, localPort); + createTunnel (gatewayHost, remoteHost, remotePort, localPort); + } + + Socket* sock = 0; + + if (listenMode) { + int port = 5500; + if (vncServerName && isdigit(vncServerName[0])) + port = atoi(vncServerName); + + TcpListener listener(port); + + vlog.info("Listening on port %d\n",port); + + while (true) { + sock = listener.accept(); + int pid = fork(); + if (pid < 0) { perror("fork"); exit(1); } + if (pid == 0) break; // child + delete sock; + int status; + while (wait3(&status, WNOHANG, 0) > 0) ; + } + } + + CharArray displaynameStr(displayname.getData()); + if (!(dpy = XOpenDisplay(TXWindow::strEmptyToNull(displaynameStr.buf)))) { + fprintf(stderr,"%s: unable to open display \"%s\"\n", + programName, XDisplayName(displaynameStr.buf)); + exit(1); + } + + TXWindow::init(dpy, "Vncviewer"); + xloginIconifier.iconify(dpy); + CConn cc(dpy, argc, argv, sock, vncServerName, listenMode); + + // X events are processed whenever reading from the socket would block. + + while (true) { + cc.getInStream()->check(1); + cc.processMsg(); + } + + } catch (rdr::EndOfStream& e) { + vlog.info(e.str()); + } catch (rdr::Exception& e) { + vlog.error(e.str()); + if (dpy) { + TXMsgBox msgBox(dpy, e.str(), MB_OK, "VNC Viewer: Information"); + msgBox.show(); + } + return 1; + } + + return 0; +} diff --git a/unix/vncviewer/vncviewer.man b/unix/vncviewer/vncviewer.man new file mode 100644 index 00000000..a805d327 --- /dev/null +++ b/unix/vncviewer/vncviewer.man @@ -0,0 +1,212 @@ +.TH vncviewer 1 "05 May 2004" "TightVNC" "Virtual Network Computing" +.SH NAME +vncviewer \- VNC viewer for X +.SH SYNOPSIS +.B vncviewer +.RI [ options ] +.RI [ host ][: display# ] +.br +.B vncviewer +.RI [ options ] +.B \-listen +.RI [ port ] +.SH DESCRIPTION +.B vncviewer +is a viewer (client) for Virtual Network Computing. This manual page documents +version 4 for the X window system. + +If you run the viewer with no arguments it will prompt you for a VNC server to +connect to. Alternatively, specify the VNC server as an argument, e.g.: + +.RS +vncviewer snoopy:2 +.RE + +where 'snoopy' is the name of the machine, and '2' is the display number of the +VNC server on that machine. Either the machine name or display number can be +omitted. So for example ":1" means display number 1 on the same machine, and +"snoopy" means "snoopy:0" i.e. display 0 on machine "snoopy". + +If the VNC server is successfully contacted, you will be prompted for a +password to authenticate you. If the password is correct, a window will appear +showing the desktop of the VNC server. + +.SH AUTOMATIC PROTOCOL SELECTION + +The viewer tests the speed of the connection to the server and chooses the +encoding and pixel format (color level) appropriately. This makes it much +easier to use than previous versions where the user had to specify arcane +command line arguments. + +The viewer normally starts out assuming the link is slow, using the +encoding with the best compression. If it turns out that the link is +fast enough it switches to an encoding which compresses less but is +faster to generate, thus improving the interactive feel. + +The viewer normally starts in full-color mode, but switches to +low-color mode if the bandwidth is insufficient. However, this only +occurs when communicating with servers supporting protocol 3.8 or +newer, since many old servers does not support color mode changes +safely. + +Automatic selection can be turned off by setting the +\fBAutoSelect\fP parameter to false, or from the options dialog. + +.SH POPUP MENU +The viewer has a popup menu containing entries which perform various actions. +It is usually brought up by pressing F8, but this can be configured with the +MenuKey parameter. Actions which the popup menu can perform include: +.RS 2 +.IP * 2 +switching in and out of full-screen mode +.IP * +quitting the viewer +.IP * +generating key events, e.g. sending ctrl-alt-del +.IP * +accessing the options dialog and various other dialogs +.RE +.PP +By default, key presses in the popup menu get sent to the VNC server and +dismiss the popup. So to get an F8 through to the VNC server simply press it +twice. + +.SH FULL SCREEN MODE +A full-screen mode is supported. This is particularly useful when connecting +to a remote screen which is the same size as your local one. If the remote +screen is bigger, you can scroll by bumping the mouse against the edge of the +screen. + +Unfortunately this mode doesn't work completely with all window managers, since +it breaks the X window management conventions. + +.SH OPTIONS (PARAMETERS) +You can get a list of parameters by giving \fB\-h\fP as a command-line option +to vncviewer. Parameters can be turned on with -\fIparam\fP or off with +-\fIparam\fP=0. Parameters which take a value can be specified as +-\fIparam\fP \fIvalue\fP. Other valid forms are \fIparam\fP\fB=\fP\fIvalue\fP +-\fIparam\fP=\fIvalue\fP --\fIparam\fP=\fIvalue\fP. Parameter names are +case-insensitive. + +Many of the parameters can also be set graphically via the options dialog box. +This can be accessed from the popup menu or from the "Connection details" +dialog box. + +.TP +.B \-display \fIXdisplay\fP +Specifies the X display on which the VNC viewer window should appear. + +.TP +.B \-geometry \fIgeometry\fP +Standard X position and sizing specification. + +.TP +.B \-listen \fI[port]\fP +Causes vncviewer to listen on the given port (default 5500) for reverse +connections from a VNC server. WinVNC supports reverse connections initiated +using the 'Add New Client' menu option or the '\-connect' command-line option. +Xvnc supports reverse connections with a helper program called +.B vncconfig. + +.TP +.B \-passwd \fIpassword-file\fP +If you are on a filesystem which gives you access to the password file used by +the server, you can specify it here to avoid typing it in. It will usually be +"~/.vnc/passwd". + +.TP +.B \-Shared +When you make a connection to a VNC server, all other existing connections are +normally closed. This option requests that they be left open, allowing you to +share the desktop with someone already using it. + +.TP +.B \-ViewOnly +Specifies that no keyboard or mouse events should be sent to the server. +Useful if you want to view a desktop without interfering; often needs to be +combined with +.B \-Shared. + +.TP +.B \-FullScreen +Start in full-screen mode. + +.TP +.B \-AutoSelect +Use automatic selection of encoding and pixel format (default is on). Normally +the viewer tests the speed of the connection to the server and chooses the +encoding and pixel format appropriately. Turn it off with \fB-AutoSelect=0\fP. + +.TP +.B \-FullColor, \-FullColour +Tells the VNC server to send full-color pixels in the best format for this +display. This is default. + +.TP +.B \-LowColorLevel, \-LowColourLevel \fIlevel\fP +Selects the reduced color level to use on slow links. \fIlevel\fP can range +from 0 to 2, 0 meaning 8 colors, 1 meaning 64 colors (the default), 2 meaning +256 colors. + +.TP +.B \-PreferredEncoding \fIencoding\fP +This option specifies the preferred encoding to use from one of "Tight", "ZRLE", +"hextile" or "raw". + +.TP +.B -UseLocalCursor +Render the mouse cursor locally if the server supports it (default is on). +This can make the interactive performance feel much better over slow links. + +.TP +.B \-WMDecorationWidth \fIw\fP, \-WMDecorationHeight \fIh\fP +The total width and height taken up by window manager decorations. This is +used to calculate the maximum size of the VNC viewer window. Default is +width 6, height 24. + +.TP +.B \-log \fIlogname\fP:\fIdest\fP:\fIlevel\fP +Configures the debug log settings. \fIdest\fP can currently be \fBstderr\fP or +\fBstdout\fP, and \fIlevel\fP is between 0 and 100, 100 meaning most verbose +output. \fIlogname\fP is usually \fB*\fP meaning all, but you can target a +specific source file if you know the name of its "LogWriter". Default is +\fB*:stderr:30\fP. + +.TP +.B \-MenuKey \fIkeysym-name\fP +This option specifies the key which brings up the popup menu. The key is +specified as an X11 keysym name (these can be obtained by removing the XK_ +prefix from the entries in "/usr/include/X11/keysymdef.h"). Default is F8. + +.TP +\fB\-via\fR \fIgateway\fR +Automatically create encrypted TCP tunnel to the \fIgateway\fR machine +before connection, connect to the \fIhost\fR through that tunnel +(TightVNC\-specific). By default, this option invokes SSH local port +forwarding, assuming that SSH client binary can be accessed as +/usr/bin/ssh. Note that when using the \fB\-via\fR option, the host +machine name should be specified as known to the gateway machine, e.g. +"localhost" denotes the \fIgateway\fR, not the machine where vncviewer +was launched. The environment variable \fIVNC_VIA_CMD\fR can override +the default tunnel command of +\fB/usr/bin/ssh\ -f\ -L\ "$L":"$H":"$R"\ "$G"\ sleep\ 20\fR. The tunnel +command is executed with the environment variables \fIL\fR, \fIH\fR, +\fIR\fR, and \fIG\fR taken the values of the local port number, the remote +host, the port number on the remote host, and the gateway machine +respectively. + +.SH SEE ALSO +.BR Xvnc (1), +.BR vncpasswd (1), +.BR vncconfig (1), +.BR vncserver (1) +.br +http://www.tightvnc.com + +.SH AUTHOR +Tristan Richardson, RealVNC Ltd. + +VNC was originally developed by the RealVNC team while at Olivetti +Research Ltd / AT&T Laboratories Cambridge. TightVNC additions was +implemented by Constantin Kaplinsky. Many other people participated in +development, testing and support. diff --git a/unix/x0vncserver/Geometry.cxx b/unix/x0vncserver/Geometry.cxx new file mode 100644 index 00000000..ccb4e699 --- /dev/null +++ b/unix/x0vncserver/Geometry.cxx @@ -0,0 +1,71 @@ +/* Copyright (C) 2006 Constantin Kaplinsky. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// Geometry.cxx +// + +#include +#include +#include + +static LogWriter vlog("Geometry"); + +StringParameter Geometry::m_geometryParam("Geometry", + "Screen area shown to VNC clients. " + "Format is x++, " + "more information in man X, section GEOMETRY SPECIFICATIONS. " + "If the argument is empty, full screen is shown to VNC clients.", + ""); + +Geometry::Geometry(int fullWidth, int fullHeight) + : m_width(fullWidth), m_height(fullHeight), + m_offsetLeft(0), m_offsetTop(0) +{ + const char *param = m_geometryParam.getData(); + if (strlen(param) != 0) { + int w, h; + int x = 0, y = 0; + char sign_x[2] = "+"; + char sign_y[2] = "+"; + int n = sscanf(param, "%dx%d%1[+-]%d%1[+-]%d", + &w, &h, sign_x, &x, sign_y, &y); + if ((n == 2 || n == 6) && w > 0 && h > 0 && x >= 0 && y >= 0) { + if (sign_x[0] == '-') + x = fullWidth - w - x; + if (sign_y[0] == '-') + y = fullHeight - h - y; + Rect fullRect(0, 0, fullWidth, fullHeight); + Rect partRect(x, y, x + w, y + h); + Rect r = partRect.intersect(fullRect); + if (r.area() > 0) { + m_width = r.width(); + m_height = r.height(); + m_offsetLeft = r.tl.x; + m_offsetTop = r.tl.y; + } else { + vlog.error("Requested area is out of the desktop boundaries"); + } + } else { + vlog.error("Wrong argument format"); + } + } + vlog.info("Desktop geometry is %dx%d+%d+%d", + m_width, m_height, m_offsetLeft, m_offsetTop); +} + diff --git a/unix/x0vncserver/Geometry.h b/unix/x0vncserver/Geometry.h new file mode 100644 index 00000000..95059e7d --- /dev/null +++ b/unix/x0vncserver/Geometry.h @@ -0,0 +1,50 @@ +/* Copyright (C) 2006 Constantin Kaplinsky. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// Geometry.h +// + +#ifndef __GEOMETRY_H__ +#define __GEOMETRY_H__ + +#include + +using namespace rfb; + +class Geometry +{ +public: + Geometry(int fullWidth, int fullHeight); + + int width() const { return m_width; } + int height() const { return m_height; } + int offsetLeft() const { return m_offsetLeft; } + int offsetTop() const { return m_offsetTop; } + +protected: + static StringParameter m_geometryParam; + + int m_width; + int m_height; + int m_offsetLeft; + int m_offsetTop; +}; + +#endif // __GEOMETRY_H__ + diff --git a/unix/x0vncserver/Image.cxx b/unix/x0vncserver/Image.cxx new file mode 100644 index 00000000..fc66c5a9 --- /dev/null +++ b/unix/x0vncserver/Image.cxx @@ -0,0 +1,549 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2004-2005 Constantin Kaplinsky. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// Image.cxx +// + +#include +#include + +#ifdef HAVE_MITSHM +#include +#include +#endif + +#include +#include + +// +// ImageCleanup is used to delete Image instances automatically on +// program shutdown. This is important for shared memory images. +// + +#include + +class ImageCleanup { +public: + std::list images; + + ~ImageCleanup() + { + while (!images.empty()) { + delete images.front(); + } + } +}; + +ImageCleanup imageCleanup; + +// +// Image class implementation. +// + +static rfb::LogWriter vlog("Image"); + +Image::Image(Display *d) + : xim(NULL), dpy(d), trueColor(true) +{ + imageCleanup.images.push_back(this); +} + +Image::Image(Display *d, int width, int height) + : xim(NULL), dpy(d), trueColor(true) +{ + imageCleanup.images.push_back(this); + Init(width, height); +} + +void Image::Init(int width, int height) +{ + Visual* vis = DefaultVisual(dpy, DefaultScreen(dpy)); + trueColor = (vis->c_class == TrueColor); + + xim = XCreateImage(dpy, vis, DefaultDepth(dpy, DefaultScreen(dpy)), + ZPixmap, 0, 0, width, height, BitmapPad(dpy), 0); + + xim->data = (char *)malloc(xim->bytes_per_line * xim->height); + if (xim->data == NULL) { + vlog.error("malloc() failed"); + exit(1); + } +} + +Image::~Image() +{ + imageCleanup.images.remove(this); + + // XDestroyImage will free xim->data if necessary + if (xim != NULL) + XDestroyImage(xim); +} + +void Image::get(Window wnd, int x, int y) +{ + get(wnd, x, y, xim->width, xim->height); +} + +void Image::get(Window wnd, int x, int y, int w, int h) +{ + XGetSubImage(dpy, wnd, x, y, w, h, AllPlanes, ZPixmap, xim, 0, 0); +} + +// +// Copying pixels from one image to another. +// +// FIXME: Use Point and Rect structures? +// FIXME: Too many similar methods? +// + +inline +void Image::copyPixels(XImage *src, + int dst_x, int dst_y, + int src_x, int src_y, + int w, int h) +{ + const char *srcOffset = + src->data + (src_y * src->bytes_per_line + + src_x * (src->bits_per_pixel / 8)); + char *dstOffset = + xim->data + (dst_y * xim->bytes_per_line + + dst_x * (xim->bits_per_pixel / 8)); + + int rowLength = w * (xim->bits_per_pixel / 8); + + for (int i = 0; i < h ; i++) { + memcpy(dstOffset, srcOffset, rowLength); + srcOffset += src->bytes_per_line; + dstOffset += xim->bytes_per_line; + } +} + +void Image::updateRect(XImage *src, int dst_x, int dst_y) +{ + // Limit width and height at destination image size. + int w = src->width; + if (dst_x + w > xim->width) + w = xim->width - dst_x; + int h = src->height; + if (dst_y + h > xim->height) + h = xim->height - dst_y; + + copyPixels(src, dst_x, dst_y, 0, 0, w, h); +} + +void Image::updateRect(Image *src, int dst_x, int dst_y) +{ + updateRect(src->xim, dst_x, dst_y); +} + +void Image::updateRect(XImage *src, int dst_x, int dst_y, int w, int h) +{ + // Correct width and height if necessary. + if (w > src->width) + w = src->width; + if (dst_x + w > xim->width) + w = xim->width - dst_x; + if (h > src->height) + h = src->height; + if (dst_y + h > xim->height) + h = xim->height - dst_y; + + copyPixels(src, dst_x, dst_y, 0, 0, w, h); +} + +void Image::updateRect(Image *src, int dst_x, int dst_y, int w, int h) +{ + updateRect(src->xim, dst_x, dst_y, w, h); +} + +void Image::updateRect(XImage *src, int dst_x, int dst_y, + int src_x, int src_y, int w, int h) +{ + // Correct width and height if necessary. + if (src_x + w > src->width) + w = src->width - src_x; + if (dst_x + w > xim->width) + w = xim->width - dst_x; + if (src_y + h > src->height) + h = src->height - src_y; + if (dst_y + h > xim->height) + h = xim->height - dst_y; + + copyPixels(src, dst_x, dst_y, src_x, src_y, w, h); +} + +void Image::updateRect(Image *src, int dst_x, int dst_y, + int src_x, int src_y, int w, int h) +{ + updateRect(src->xim, dst_x, dst_y, src_x, src_y, w, h); +} + +#ifdef HAVE_MITSHM + +// +// ShmImage class implementation. +// + +static bool caughtShmError = false; + +static int ShmCreationXErrorHandler(Display *dpy, XErrorEvent *error) +{ + caughtShmError = true; + return 0; +} + +ShmImage::ShmImage(Display *d) + : Image(d), shminfo(NULL) +{ +} + +ShmImage::ShmImage(Display *d, int width, int height) + : Image(d), shminfo(NULL) +{ + Init(width, height); +} + +// FIXME: Remove duplication of cleanup operations. +void ShmImage::Init(int width, int height, const XVisualInfo *vinfo) +{ + int major, minor; + Bool pixmaps; + + if (!XShmQueryVersion(dpy, &major, &minor, &pixmaps)) { + vlog.error("XShmQueryVersion() failed"); + return; + } + + Visual *visual; + int depth; + + if (vinfo == NULL) { + visual = DefaultVisual(dpy, DefaultScreen(dpy)); + depth = DefaultDepth(dpy, DefaultScreen(dpy)); + } else { + visual = vinfo->visual; + depth = vinfo->depth; + } + + trueColor = (visual->c_class == TrueColor); + + shminfo = new XShmSegmentInfo; + + xim = XShmCreateImage(dpy, visual, depth, ZPixmap, 0, shminfo, + width, height); + if (xim == NULL) { + vlog.error("XShmCreateImage() failed"); + delete shminfo; + shminfo = NULL; + return; + } + + shminfo->shmid = shmget(IPC_PRIVATE, + xim->bytes_per_line * xim->height, + IPC_CREAT|0777); + if (shminfo->shmid == -1) { + perror("shmget"); + vlog.error("shmget() failed (%d bytes requested)", + int(xim->bytes_per_line * xim->height)); + XDestroyImage(xim); + xim = NULL; + delete shminfo; + shminfo = NULL; + return; + } + + shminfo->shmaddr = xim->data = (char *)shmat(shminfo->shmid, 0, 0); + if (shminfo->shmaddr == (char *)-1) { + perror("shmat"); + vlog.error("shmat() failed (%d bytes requested)", + int(xim->bytes_per_line * xim->height)); + shmctl(shminfo->shmid, IPC_RMID, 0); + XDestroyImage(xim); + xim = NULL; + delete shminfo; + shminfo = NULL; + return; + } + + shminfo->readOnly = False; + + XErrorHandler oldHdlr = XSetErrorHandler(ShmCreationXErrorHandler); + XShmAttach(dpy, shminfo); + XSync(dpy, False); + XSetErrorHandler(oldHdlr); + if (caughtShmError) { + vlog.error("XShmAttach() failed"); + shmdt(shminfo->shmaddr); + shmctl(shminfo->shmid, IPC_RMID, 0); + XDestroyImage(xim); + xim = NULL; + delete shminfo; + shminfo = NULL; + return; + } +} + +ShmImage::~ShmImage() +{ + // FIXME: Destroy image as described in MIT-SHM documentation. + if (shminfo != NULL) { + shmdt(shminfo->shmaddr); + shmctl(shminfo->shmid, IPC_RMID, 0); + delete shminfo; + } +} + +void ShmImage::get(Window wnd, int x, int y) +{ + XShmGetImage(dpy, wnd, xim, x, y, AllPlanes); +} + +void ShmImage::get(Window wnd, int x, int y, int w, int h) +{ + // FIXME: Use SHM for this as well? + XGetSubImage(dpy, wnd, x, y, w, h, AllPlanes, ZPixmap, xim, 0, 0); +} + +#ifdef HAVE_READDISPLAY + +// +// IrixOverlayShmImage class implementation. +// + +IrixOverlayShmImage::IrixOverlayShmImage(Display *d) + : ShmImage(d), readDisplayBuf(NULL) +{ +} + +IrixOverlayShmImage::IrixOverlayShmImage(Display *d, int width, int height) + : ShmImage(d), readDisplayBuf(NULL) +{ + Init(width, height); +} + +void IrixOverlayShmImage::Init(int width, int height) +{ + // First determine the pixel format used by XReadDisplay. + XVisualInfo vinfo; + if (!getOverlayVisualInfo(&vinfo)) + return; + + // Create an SHM image of the same format. + ShmImage::Init(width, height, &vinfo); + if (xim == NULL) + return; + + // FIXME: Check if the extension is available at run time. + readDisplayBuf = XShmCreateReadDisplayBuf(dpy, NULL, shminfo, width, height); +} + +bool IrixOverlayShmImage::getOverlayVisualInfo(XVisualInfo *vinfo_ret) +{ + // First, get an image in the format returned by XReadDisplay. + unsigned long hints = 0, hints_ret; + XImage *testImage = XReadDisplay(dpy, DefaultRootWindow(dpy), + 0, 0, 8, 8, hints, &hints_ret); + if (testImage == NULL) + return false; + + // Fill in a template for matching visuals. + XVisualInfo tmpl; + tmpl.c_class = TrueColor; + tmpl.depth = 24; + tmpl.red_mask = testImage->red_mask; + tmpl.green_mask = testImage->green_mask; + tmpl.blue_mask = testImage->blue_mask; + + // List fields in template that make sense. + long mask = (VisualClassMask | + VisualRedMaskMask | + VisualGreenMaskMask | + VisualBlueMaskMask); + + // We don't need that image any more. + XDestroyImage(testImage); + + // Now, get a list of matching visuals available. + int nVisuals; + XVisualInfo *vinfo = XGetVisualInfo(dpy, mask, &tmpl, &nVisuals); + if (vinfo == NULL || nVisuals <= 0) { + if (vinfo != NULL) { + XFree(vinfo); + } + return false; + } + + // Use first visual from the list. + *vinfo_ret = vinfo[0]; + + XFree(vinfo); + + return true; +} + +IrixOverlayShmImage::~IrixOverlayShmImage() +{ + if (readDisplayBuf != NULL) + XShmDestroyReadDisplayBuf(readDisplayBuf); +} + +void IrixOverlayShmImage::get(Window wnd, int x, int y) +{ + get(wnd, x, y, xim->width, xim->height); +} + +void IrixOverlayShmImage::get(Window wnd, int x, int y, int w, int h) +{ + XRectangle rect; + unsigned long hints = XRD_TRANSPARENT | XRD_READ_POINTER; + + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + + XShmReadDisplayRects(dpy, wnd, + &rect, 1, readDisplayBuf, -x, -y, + hints, &hints); +} + +#endif // HAVE_READDISPLAY +#endif // HAVE_MITSHM + +#ifdef HAVE_SUN_OVL + +// +// SolarisOverlayImage class implementation +// + +SolarisOverlayImage::SolarisOverlayImage(Display *d) + : Image(d) +{ +} + +SolarisOverlayImage::SolarisOverlayImage(Display *d, int width, int height) + : Image(d) +{ + Init(width, height); +} + +void SolarisOverlayImage::Init(int width, int height) +{ + // FIXME: Check if the extension is available at run time. + // FIXME: Maybe just read a small (e.g. 8x8) screen area then + // reallocate xim->data[] and correct width and height? + xim = XReadScreen(dpy, DefaultRootWindow(dpy), 0, 0, width, height, True); + if (xim == NULL) { + vlog.error("XReadScreen() failed"); + return; + } +} + +SolarisOverlayImage::~SolarisOverlayImage() +{ +} + +void SolarisOverlayImage::get(Window wnd, int x, int y) +{ + get(wnd, x, y, xim->width, xim->height); +} + +void SolarisOverlayImage::get(Window wnd, int x, int y, int w, int h) +{ + XImage *tmp_xim = XReadScreen(dpy, wnd, x, y, w, h, True); + if (tmp_xim == NULL) + return; + + updateRect(tmp_xim, 0, 0); + + XDestroyImage(tmp_xim); +} + +#endif // HAVE_SUN_OVL + +// +// ImageFactory class implementation +// +// FIXME: Make ImageFactory always create images of the same class? +// + +// Prepare useful shortcuts for compile-time options. +#if defined(HAVE_READDISPLAY) && defined(HAVE_MITSHM) +#define HAVE_SHM_READDISPLAY +#endif +#if defined(HAVE_SHM_READDISPLAY) || defined(HAVE_SUN_OVL) +#define HAVE_OVERLAY_EXT +#endif + +ImageFactory::ImageFactory(bool allowShm, bool allowOverlay) + : mayUseShm(allowShm), mayUseOverlay(allowOverlay) +{ +} + +ImageFactory::~ImageFactory() +{ +} + +Image *ImageFactory::newImage(Display *d, int width, int height) +{ + Image *image = NULL; + + // First, try to create an image with overlay support. + +#ifdef HAVE_OVERLAY_EXT + if (mayUseOverlay) { +#if defined(HAVE_SHM_READDISPLAY) + if (mayUseShm) { + image = new IrixOverlayShmImage(d, width, height); + if (image->xim != NULL) { + return image; + } + } +#elif defined(HAVE_SUN_OVL) + image = new SolarisOverlayImage(d, width, height); + if (image->xim != NULL) { + return image; + } +#endif + if (image != NULL) { + delete image; + vlog.error("Failed to create overlay image, trying other options"); + } + } +#endif // HAVE_OVERLAY_EXT + + // Now, try to use shared memory image. + +#ifdef HAVE_MITSHM + if (mayUseShm) { + image = new ShmImage(d, width, height); + if (image->xim != NULL) { + return image; + } + + delete image; + vlog.error("Failed to create SHM image, falling back to Xlib image"); + } +#endif // HAVE_MITSHM + + // Fall back to Xlib image. + + image = new Image(d, width, height); + return image; +} diff --git a/unix/x0vncserver/Image.h b/unix/x0vncserver/Image.h new file mode 100644 index 00000000..535cee6a --- /dev/null +++ b/unix/x0vncserver/Image.h @@ -0,0 +1,223 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2004-2005 Constantin Kaplinsky. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// Image.h +// + +#ifndef __IMAGE_H__ +#define __IMAGE_H__ + +#include +#include + +// +// Image class is an Xlib-based implementation of screen image storage. +// + +class Image { + +public: + + Image(Display *d); + Image(Display *d, int width, int height); + virtual ~Image(); + + bool isTrueColor() const { return trueColor; } + + virtual const char *className() const { + return "Image"; + } + virtual const char *classDesc() const { + return "basic Xlib image"; + } + + virtual void get(Window wnd, int x = 0, int y = 0); + virtual void get(Window wnd, int x, int y, int w, int h); + +// Copying pixels from one image to another. + virtual void updateRect(XImage *src, int dst_x = 0, int dst_y = 0); + virtual void updateRect(Image *src, int dst_x = 0, int dst_y = 0); + virtual void updateRect(XImage *src, int dst_x, int dst_y, int w, int h); + virtual void updateRect(Image *src, int dst_x, int dst_y, int w, int h); + virtual void updateRect(XImage *src, int dst_x, int dst_y, + int src_x, int src_y, int w, int h); + virtual void updateRect(Image *src, int dst_x, int dst_y, + int src_x, int src_y, int w, int h); + + // Pointer to corresponding XImage, made public for efficiency. + // NOTE: if this field is NULL, then no methods other than Init() + // may be called. + XImage* xim; + +protected: + + void Init(int width, int height); + + // Like updateRect(), but does not check arguments. + void copyPixels(XImage *src, + int dst_x, int dst_y, + int src_x, int src_y, + int w, int h); + + Display *dpy; + bool trueColor; + +}; + +// +// ShmImage uses MIT-SHM extension of an X server to get image data. +// + +#ifdef HAVE_MITSHM + +#include + +class ShmImage : public Image { + +public: + + ShmImage(Display *d); + ShmImage(Display *d, int width, int height); + virtual ~ShmImage(); + + virtual const char *className() const { + return "ShmImage"; + } + virtual const char *classDesc() const { + return "shared memory image"; + } + + virtual void get(Window wnd, int x = 0, int y = 0); + virtual void get(Window wnd, int x, int y, int w, int h); + +protected: + + void Init(int width, int height, const XVisualInfo *vinfo = NULL); + + XShmSegmentInfo *shminfo; + +}; + +// +// IrixOverlayShmImage uses ReadDisplay extension of an X server to +// get truecolor image data, regardless of the default X visual type. +// This method is available on Irix only. +// + +#ifdef HAVE_READDISPLAY + +#include + +class IrixOverlayShmImage : public ShmImage { + +public: + + IrixOverlayShmImage(Display *d); + IrixOverlayShmImage(Display *d, int width, int height); + virtual ~IrixOverlayShmImage(); + + virtual const char *className() const { + return "IrixOverlayShmImage"; + } + virtual const char *classDesc() const { + return "IRIX-specific SHM-aware overlay image"; + } + + virtual void get(Window wnd, int x = 0, int y = 0); + virtual void get(Window wnd, int x, int y, int w, int h); + +protected: + + void Init(int width, int height); + + // This method searches available X visuals for one that matches + // actual pixel format returned by XReadDisplay(). Returns true on + // success, false if there is no matching visual. On success, visual + // information is placed into the structure pointed by vinfo_ret. + bool getOverlayVisualInfo(XVisualInfo *vinfo_ret); + + ShmReadDisplayBuf *readDisplayBuf; + +}; + +#endif // HAVE_READDISPLAY +#endif // HAVE_MITSHM + +// +// SolarisOverlayImage uses SUN_OVL extension of an X server to get +// truecolor image data, regardless of the default X visual type. This +// method is available on Solaris only. +// + +#ifdef HAVE_SUN_OVL + +#include + +class SolarisOverlayImage : public Image { + +public: + + SolarisOverlayImage(Display *d); + SolarisOverlayImage(Display *d, int width, int height); + virtual ~SolarisOverlayImage(); + + virtual const char *className() const { + return "SolarisOverlayImage"; + } + virtual const char *classDesc() const { + return "Solaris-specific non-SHM overlay image"; + } + + virtual void get(Window wnd, int x = 0, int y = 0); + virtual void get(Window wnd, int x, int y, int w, int h); + +protected: + + void Init(int width, int height); + +}; + +#endif // HAVE_SUN_OVL + +// +// ImageFactory class is used to produce instances of Image-derived +// objects that are most appropriate for current X server and user +// settings. +// + +class ImageFactory { + +public: + + ImageFactory(bool allowShm, bool allowOverlay); + virtual ~ImageFactory(); + + bool isShmAllowed() { return mayUseShm; } + bool isOverlayAllowed() { return mayUseOverlay; } + + virtual Image *newImage(Display *d, int width, int height); + +protected: + + bool mayUseShm; + bool mayUseOverlay; + +}; + +#endif // __IMAGE_H__ diff --git a/unix/x0vncserver/Makefile.in b/unix/x0vncserver/Makefile.in new file mode 100644 index 00000000..cbb9fed6 --- /dev/null +++ b/unix/x0vncserver/Makefile.in @@ -0,0 +1,30 @@ + +SRCS = Image.cxx TimeMillis.cxx PollingScheduler.cxx PollingManager.cxx \ + Geometry.cxx \ + x0vncserver.cxx ../vncconfig_unix/QueryConnectDialog.cxx + +OBJS = $(SRCS:.cxx=.o) + +program = x0vncserver + +DEP_LIBS = ../rfb/librfb.a \ + ../network/libnetwork.a \ + ../rdr/librdr.a \ + ../tx/libtx.a + +EXTRA_LIBS = @ZLIB_LIB@ @JPEG_LIB@ @INET_LIB@ @X_PRE_LIBS@ @X_LIBS@ \ + @XTEST_LIB@ -lXext -lX11 @X_EXTRA_LIBS@ + +# X_CFLAGS are really CPPFLAGS +DIR_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/tx -I$(top_srcdir)/vncconfig_unix \ + @XTEST_DEFINE@ @READDISPLAY_DEFINE@ @MITSHM_DEFINE@ @X_CFLAGS@ + +all:: $(program) + +$(program): $(OBJS) buildtime.o $(DEP_LIBS) + rm -f $(program) + $(CXXLD) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJS) buildtime.o $(DEP_LIBS) $(LIBS) $(EXTRA_LIBS) + +buildtime.o: $(OBJS) $(DEP_LIBS) + +# followed by boilerplate.mk diff --git a/unix/x0vncserver/PollingManager.cxx b/unix/x0vncserver/PollingManager.cxx new file mode 100644 index 00000000..a823ed42 --- /dev/null +++ b/unix/x0vncserver/PollingManager.cxx @@ -0,0 +1,600 @@ +/* Copyright (C) 2004-2005 Constantin Kaplinsky. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// PollingManager.cxx +// + +// FIXME: Don't compare pixels already marked as changed. +// FIXME: Use Image::copyPixels() instead of Image::updateRect()? +// In that case, note the fact that arguments are not checked. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static LogWriter vlog("PollingMgr"); + +BoolParameter PollingManager::pollPointer +("PollPointer", + "DEBUG: Poll area under the pointer with higher priority", + true); + +IntParameter PollingManager::pollingType +("PollingType", + "DEBUG: Select particular polling algorithm (0..3)", + 3); + +const int PollingManager::m_pollingOrder[32] = { + 0, 16, 8, 24, 4, 20, 12, 28, + 10, 26, 18, 2, 22, 6, 30, 14, + 1, 17, 9, 25, 7, 23, 15, 31, + 19, 3, 27, 11, 29, 13, 5, 21 +}; + +// +// Constructor. +// +// Note that dpy and image should remain valid during the object +// lifetime, while factory is used only in the constructor itself. +// + +PollingManager::PollingManager(Display *dpy, Image *image, + ImageFactory *factory, + int offsetLeft, int offsetTop) + : m_dpy(dpy), m_server(0), m_image(image), + m_offsetLeft(offsetLeft), m_offsetTop(offsetTop), + m_pointerPosKnown(false), m_pollingStep(0) +{ + // Save width and height of the screen (and the image). + m_width = m_image->xim->width; + m_height = m_image->xim->height; + + // Compute width and height in 32x32 tiles. + m_widthTiles = (m_width + 31) / 32; + m_heightTiles = (m_height + 31) / 32; + + // Get initial screen image. + m_image->get(DefaultRootWindow(m_dpy), m_offsetLeft, m_offsetTop); + + // Create additional images used in polling algorithms, warn if + // underlying class names are different from the class name of the + // primary image. + m_rowImage = factory->newImage(m_dpy, m_width, 1); + m_tileImage = factory->newImage(m_dpy, 32, 32); + m_areaImage = factory->newImage(m_dpy, 128, 128); + if (strcmp(m_image->className(), m_rowImage->className()) != 0 || + strcmp(m_image->className(), m_tileImage->className()) != 0 || + strcmp(m_image->className(), m_areaImage->className()) != 0) { + vlog.error("Image types do not match (%s, %s, %s)", + m_rowImage->className(), + m_tileImage->className(), + m_areaImage->className()); + } + + // FIXME: Extend the comment. + // Create a matrix with one byte per each 32x32 tile. It will be + // used to limit the rate of updates on continuously-changed screen + // areas (like video). + int numTiles = m_widthTiles * m_heightTiles; + m_statusMatrix = new char[numTiles]; + memset(m_statusMatrix, 0, numTiles); + + // FIXME: Extend the comment. + // Create a matrix with one byte per each 32x32 tile. It will be + // used to limit the rate of updates on continuously-changed screen + // areas (like video). + m_rateMatrix = new char[numTiles]; + m_videoFlags = new char[numTiles]; + m_changedFlags = new char[numTiles]; + memset(m_rateMatrix, 0, numTiles); + memset(m_videoFlags, 0, numTiles); + memset(m_changedFlags, 0, numTiles); +} + +PollingManager::~PollingManager() +{ + delete[] m_changedFlags; + delete[] m_videoFlags; + delete[] m_rateMatrix; + + delete[] m_statusMatrix; + + delete m_areaImage; + delete m_tileImage; + delete m_rowImage; +} + +// +// Register VNCServer object. +// + +void PollingManager::setVNCServer(VNCServer *s) +{ + m_server = s; +} + +// +// Update current pointer position which may be used as a hint for +// polling algorithms. +// + +void PollingManager::setPointerPos(const Point &pos) +{ + m_pointerPosTime = time(NULL); + m_pointerPos = pos; + m_pointerPosKnown = true; +} + +// +// Indicate that current pointer position is unknown. +// + +void PollingManager::unsetPointerPos() +{ + m_pointerPosKnown = false; +} + +// +// DEBUG: Measuring time spent in the poll() function, +// as well as time intervals between poll() calls. +// + +#ifdef DEBUG +void PollingManager::debugBeforePoll() +{ + TimeMillis timeNow; + int diff = timeNow.diffFrom(m_timeSaved); + fprintf(stderr, "[wait%4dms]\t[step %2d]\t", diff, m_pollingStep % 32); + m_timeSaved = timeNow; +} + +void PollingManager::debugAfterPoll() +{ + TimeMillis timeNow; + int diff = timeNow.diffFrom(m_timeSaved); + fprintf(stderr, "[poll%4dms]\n", diff); + m_timeSaved = timeNow; +} + +#endif + +// +// Search for changed rectangles on the screen. +// + +void PollingManager::poll() +{ +#ifdef DEBUG + debugBeforePoll(); +#endif + + // First step: full-screen polling. + + bool changes1 = false; + + switch((int)pollingType) { + case 0: + changes1 = poll_Dumb(); + break; + case 1: + changes1 = poll_Traditional(); + break; + case 2: + changes1 = poll_SkipCycles(); + break; +//case 3: + default: + changes1 = poll_DetectVideo(); + break; + } + + // Second step: optional thorough polling of the area around the pointer. + // We do that only if the pointer position is known and was set recently. + + bool changes2 = false; + if (pollPointer) { + if (m_pointerPosKnown && time(NULL) - m_pointerPosTime >= 5) { + unsetPointerPos(); + } + if (m_pointerPosKnown) { + changes2 = pollPointerArea(); + } + } + + // Update if needed. + + if (changes1 || changes2) + m_server->tryUpdate(); + +#ifdef DEBUG + debugAfterPoll(); +#endif +} + +bool PollingManager::poll_DetectVideo() +{ + if (!m_server) + return false; + + const int GRAND_STEP_DIVISOR = 8; + const int VIDEO_THRESHOLD_0 = 3; + const int VIDEO_THRESHOLD_1 = 5; + + bool grandStep = (m_pollingStep % GRAND_STEP_DIVISOR == 0); + + // FIXME: Save shortcuts in member variables? + int scanLine = m_pollingOrder[m_pollingStep++ % 32]; + int bytesPerPixel = m_image->xim->bits_per_pixel / 8; + int bytesPerLine = m_image->xim->bytes_per_line; + + Rect rect; + int nTilesChanged = 0; + int idx = 0; + + for (int y = 0; y * 32 < m_height; y++) { + int tile_h = (m_height - y * 32 >= 32) ? 32 : m_height - y * 32; + if (scanLine >= tile_h) + break; + int scan_y = y * 32 + scanLine; + getRow(scan_y); + char *ptr_old = m_image->xim->data + scan_y * bytesPerLine; + char *ptr_new = m_rowImage->xim->data; + for (int x = 0; x * 32 < m_width; x++) { + int tile_w = (m_width - x * 32 >= 32) ? 32 : m_width - x * 32; + int nBytes = tile_w * bytesPerPixel; + + char wasChanged = (memcmp(ptr_old, ptr_new, nBytes) != 0); + m_rateMatrix[idx] += wasChanged; + + if (grandStep) { + if (m_rateMatrix[idx] <= VIDEO_THRESHOLD_0) { + m_videoFlags[idx] = 0; + } else if (m_rateMatrix[idx] >= VIDEO_THRESHOLD_1) { + m_videoFlags[idx] = 1; + } + m_rateMatrix[idx] = 0; + } + + m_changedFlags[idx] |= wasChanged; + if ( m_changedFlags[idx] && (!m_videoFlags[idx] || grandStep) ) { + getTile32(x, y, tile_w, tile_h); + m_image->updateRect(m_tileImage, x * 32, y * 32); + rect.setXYWH(x * 32, y * 32, tile_w, tile_h); + m_server->add_changed(rect); + nTilesChanged++; + m_changedFlags[idx] = 0; + } + + ptr_old += nBytes; + ptr_new += nBytes; + idx++; + } + } + + if (grandStep) + adjustVideoArea(); + + return (nTilesChanged != 0); +} + +bool PollingManager::poll_SkipCycles() +{ + if (!m_server) + return false; + + enum { + NOT_CHANGED, CHANGED_ONCE, CHANGED_AGAIN + }; + + bool grandStep = (m_pollingStep % 8 == 0); + + int nTilesChanged = 0; + int scanLine = m_pollingOrder[m_pollingStep++ % 32]; + int bytesPerPixel = m_image->xim->bits_per_pixel / 8; + int bytesPerLine = m_image->xim->bytes_per_line; + char *pstatus = m_statusMatrix; + bool wasChanged; + Rect rect; + + for (int y = 0; y * 32 < m_height; y++) { + int tile_h = (m_height - y * 32 >= 32) ? 32 : m_height - y * 32; + if (scanLine >= tile_h) + scanLine %= tile_h; + int scan_y = y * 32 + scanLine; + getRow(scan_y); + char *ptr_old = m_image->xim->data + scan_y * bytesPerLine; + char *ptr_new = m_rowImage->xim->data; + for (int x = 0; x * 32 < m_width; x++) { + int tile_w = (m_width - x * 32 >= 32) ? 32 : m_width - x * 32; + int nBytes = tile_w * bytesPerPixel; + + if (grandStep || *pstatus != CHANGED_AGAIN) { + wasChanged = (*pstatus == CHANGED_AGAIN) ? + true : (memcmp(ptr_old, ptr_new, nBytes) != 0); + if (wasChanged) { + if (grandStep || *pstatus == NOT_CHANGED) { + getTile32(x, y, tile_w, tile_h); + m_image->updateRect(m_tileImage, x * 32, y * 32); + rect.setXYWH(x * 32, y * 32, tile_w, tile_h); + m_server->add_changed(rect); + nTilesChanged++; + *pstatus = CHANGED_ONCE; + } else { + *pstatus = CHANGED_AGAIN; + } + } else if (grandStep) { + *pstatus = NOT_CHANGED; + } + } + + ptr_old += nBytes; + ptr_new += nBytes; + pstatus++; + } + } + + return (nTilesChanged != 0); +} + +bool PollingManager::poll_Traditional() +{ + if (!m_server) + return false; + + int nTilesChanged = 0; + int scanLine = m_pollingOrder[m_pollingStep++ % 32]; + int bytesPerPixel = m_image->xim->bits_per_pixel / 8; + int bytesPerLine = m_image->xim->bytes_per_line; + Rect rect; + + for (int y = 0; y * 32 < m_height; y++) { + int tile_h = (m_height - y * 32 >= 32) ? 32 : m_height - y * 32; + if (scanLine >= tile_h) + break; + int scan_y = y * 32 + scanLine; + getRow(scan_y); + char *ptr_old = m_image->xim->data + scan_y * bytesPerLine; + char *ptr_new = m_rowImage->xim->data; + for (int x = 0; x * 32 < m_width; x++) { + int tile_w = (m_width - x * 32 >= 32) ? 32 : m_width - x * 32; + int nBytes = tile_w * bytesPerPixel; + if (memcmp(ptr_old, ptr_new, nBytes)) { + getTile32(x, y, tile_w, tile_h); + m_image->updateRect(m_tileImage, x * 32, y * 32); + rect.setXYWH(x * 32, y * 32, tile_w, tile_h); + m_server->add_changed(rect); + nTilesChanged++; + } + ptr_old += nBytes; + ptr_new += nBytes; + } + } + + return (nTilesChanged != 0); +} + +// +// Simplest polling method, from the original x0vncserver of VNC4. +// + +bool PollingManager::poll_Dumb() +{ + if (!m_server) + return false; + + getScreen(); + Rect rect(0, 0, m_width, m_height); + m_server->add_changed(rect); + + // Report that some changes have been detected. + return true; +} + +// +// Compute coordinates of the rectangle around the pointer. +// +// ASSUMES: (m_pointerPosKnown != false) +// + +void PollingManager::computePointerArea(Rect *r) +{ + int x = m_pointerPos.x - 64; + int y = m_pointerPos.y - 64; + int w = 128; + int h = 128; + if (x < 0) { + w += x; x = 0; + } + if (x + w > m_width) { + w = m_width - x; + } + if (y < 0) { + h += y; y = 0; + } + if (y + h > m_height) { + h = m_height - y; + } + + r->setXYWH(x, y, w, h); +} + +// +// Poll the area under current pointer position. Each pixel of the +// area should be compared. Using such polling option gives higher +// priority to screen area under the pointer. +// +// ASSUMES: (m_server != NULL && m_pointerPosKnown != false) +// + +bool PollingManager::pollPointerArea() +{ + Rect r; + computePointerArea(&r); + + // Shortcuts for coordinates. + int x = r.tl.x, y = r.tl.y; + int w = r.width(), h = r.height(); + + // Get new pixels. + getArea128(x, y, w, h); + + // Now, try to minimize the rectangle by cutting out unchanged + // borders (at top and bottom). + // + // FIXME: Perhaps we should work on 32x32 tiles (properly aligned) + // to produce a region instead of a rectangle. If there would + // be just one universal polling algorithm, it could be + // better to integrate pointer area polling into that + // algorithm, instead of a separate pollPointerArea() + // function. + + // Shortcuts. + int bytesPerPixel = m_image->xim->bits_per_pixel / 8; + int oldBytesPerLine = m_image->xim->bytes_per_line; + int newBytesPerLine = m_areaImage->xim->bytes_per_line; + char *oldPtr = m_image->xim->data + y * oldBytesPerLine + x * bytesPerPixel; + char *newPtr = m_areaImage->xim->data; + + // Check and cut out unchanged rows at the top. + int ty; + for (ty = 0; ty < h; ty++) { + if (memcmp(oldPtr, newPtr, w * bytesPerPixel) != 0) + break; + oldPtr += oldBytesPerLine; + newPtr += newBytesPerLine; + } + if (ty == h) { + return false; // no changes at all + } + y += ty; h -= ty; + + // Check and cut out unchanged rows at the bottom. + oldPtr = m_image->xim->data + (y+h-1) * oldBytesPerLine + x * bytesPerPixel; + newPtr = m_areaImage->xim->data + (ty+h-1) * newBytesPerLine; + int by; + for (by = 0; by < h - 1; by++) { + if (memcmp(oldPtr, newPtr, w * bytesPerPixel) != 0) + break; + oldPtr -= oldBytesPerLine; + newPtr -= newBytesPerLine; + } + h -= by; + + // Copy pixels. + m_image->updateRect(m_areaImage, x, y, 0, ty, w, h); + + // Report updates to the server. + Rect rect(x, y, x+w, y+h); + m_server->add_changed(rect); + return true; +} + +// +// Make video area pattern more regular. +// +// FIXME: Replace the above with a normal comment. +// FIXME: Is the function efficient enough? +// + +void PollingManager::adjustVideoArea() +{ + char newFlags[m_widthTiles * m_heightTiles]; + char *ptr = newFlags; + int x, y; + + // DEBUG: + // int nVideoTiles = 0; + + for (y = 0; y < m_heightTiles; y++) { + for (x = 0; x < m_widthTiles; x++) { + + // DEBUG: + // nVideoTiles += m_videoFlags[y * m_widthTiles + x]; + + int weightedSum = 0, n; + if (y > 0 && x > 0) { + n = (m_videoFlags[ y * m_widthTiles + (x-1)] + + m_videoFlags[(y-1) * m_widthTiles + (x-1)] + + m_videoFlags[(y-1) * m_widthTiles + x ]); + if (n == 3) { + *ptr++ = 1; + continue; + } + weightedSum += n; + } + if (y > 0 && x < m_widthTiles - 1) { + n = (m_videoFlags[ y * m_widthTiles + (x+1)] + + m_videoFlags[(y-1) * m_widthTiles + (x+1)] + + m_videoFlags[(y-1) * m_widthTiles + x ]); + if (n == 3) { + *ptr++ = 1; + continue; + } + weightedSum += n; + } + if (y < m_heightTiles - 1 && x > 0) { + n = (m_videoFlags[ y * m_widthTiles + (x-1)] + + m_videoFlags[(y+1) * m_widthTiles + (x-1)] + + m_videoFlags[(y+1) * m_widthTiles + x ]); + if (n == 3) { + *ptr++ = 1; + continue; + } + weightedSum += n; + } + if (y < m_heightTiles - 1 && x < m_widthTiles - 1) { + n = (m_videoFlags[ y * m_widthTiles + (x+1)] + + m_videoFlags[(y+1) * m_widthTiles + (x+1)] + + m_videoFlags[(y+1) * m_widthTiles + x ]); + if (n == 3) { + *ptr++ = 1; + continue; + } + weightedSum += n; + } + *ptr++ = (weightedSum <= 3) ? 0 : m_videoFlags[y * m_widthTiles + x]; + } + } + + /* + /// DEBUG: ------------------------------------------------------ + if (nVideoTiles) { + for (y = 0; y < m_heightTiles; y++) { + for (x = 0; x < m_widthTiles; x++) { + printf("%c", m_videoFlags[y * m_widthTiles + x] ? '@' : ':'); + } + printf(" "); + for (x = 0; x < m_widthTiles; x++) { + printf("%c", newFlags[y * m_widthTiles + x] ? '@' : ':'); + } + printf("\n"); + } + printf("\n"); + } + /// ------------------------------------------------------------- + */ + + memcpy(m_videoFlags, newFlags, m_widthTiles * m_heightTiles); +} diff --git a/unix/x0vncserver/PollingManager.h b/unix/x0vncserver/PollingManager.h new file mode 100644 index 00000000..b8eef509 --- /dev/null +++ b/unix/x0vncserver/PollingManager.h @@ -0,0 +1,148 @@ +/* Copyright (C) 2004-2005 Constantin Kaplinsky. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// PollingManager.h +// + +#ifndef __POLLINGMANAGER_H__ +#define __POLLINGMANAGER_H__ + +#include +#include + +#include + +#ifdef DEBUG +#include +#endif + +using namespace rfb; + +class PollingManager { + +public: + + PollingManager(Display *dpy, Image *image, ImageFactory *factory, + int offsetLeft = 0, int offsetTop = 0); + virtual ~PollingManager(); + + void setVNCServer(VNCServer *s); + + void setPointerPos(const Point &pos); + void unsetPointerPos(); + + void poll(); + + // Configurable parameters. + static BoolParameter pollPointer; + static IntParameter pollingType; + +protected: + + // + // Implementations of different polling algorithms. + // Return value of true reports that some changes were detected. + // + bool poll_DetectVideo(); + bool poll_SkipCycles(); + bool poll_Traditional(); + bool poll_Dumb(); + + // Separate polling for the area around current pointer position. + void computePointerArea(Rect *r); + bool pollPointerArea(); + + Display *m_dpy; + VNCServer *m_server; + + Image *m_image; + int m_offsetLeft; + int m_offsetTop; + int m_width; + int m_height; + int m_widthTiles; + int m_heightTiles; + + // Tracking pointer position for polling improvements. + bool m_pointerPosKnown; + Point m_pointerPos; + time_t m_pointerPosTime; + +private: + + inline void getScreen() { + m_image->get(DefaultRootWindow(m_dpy), m_offsetLeft, m_offsetTop); + } + + inline void getRow(int y) { + m_rowImage->get(DefaultRootWindow(m_dpy), m_offsetLeft, m_offsetTop + y); + } + + inline void getTile32(int tx, int ty, int w, int h) { + if (w == 32 && h == 32) { + // This version of get() may be better optimized. + m_tileImage->get(DefaultRootWindow(m_dpy), + m_offsetLeft + tx * 32, m_offsetTop + ty * 32); + } else { + // Generic version of get() for arbitrary width and height. + m_tileImage->get(DefaultRootWindow(m_dpy), + m_offsetLeft + tx * 32, m_offsetTop + ty * 32, w, h); + } + } + + inline void getArea128(int x, int y, int w, int h) { + if (w == 128 && h == 128) { + // This version of get() may be better optimized. + m_areaImage->get(DefaultRootWindow(m_dpy), + m_offsetLeft + x, m_offsetTop + y); + } else { + // Generic version of get() for arbitrary width and height. + m_areaImage->get(DefaultRootWindow(m_dpy), + m_offsetLeft + x, m_offsetTop + y, w, h); + } + } + + void adjustVideoArea(); + + // Additional images used in polling algorithms. + Image *m_rowImage; // One row of the framebuffer + Image *m_tileImage; // One tile (32x32 or less) + Image *m_areaImage; // Area around the pointer (up to 128x128) + + char *m_statusMatrix; + + char *m_rateMatrix; + char *m_videoFlags; + char *m_changedFlags; + + unsigned int m_pollingStep; + static const int m_pollingOrder[]; + +#ifdef DEBUG +private: + + void debugBeforePoll(); + void debugAfterPoll(); + + TimeMillis m_timeSaved; +#endif + +}; + +#endif // __POLLINGMANAGER_H__ diff --git a/unix/x0vncserver/PollingScheduler.cxx b/unix/x0vncserver/PollingScheduler.cxx new file mode 100644 index 00000000..c9d8d602 --- /dev/null +++ b/unix/x0vncserver/PollingScheduler.cxx @@ -0,0 +1,211 @@ +/* Copyright (C) 2006 Constantin Kaplinsky. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// PollingScheduler class implementation. +// + +#include +#include + +#ifdef DEBUG +#include +#endif + +#include + +PollingScheduler::PollingScheduler(int interval, int maxload) +{ + setParameters(interval, maxload); + reset(); +} + +void PollingScheduler::setParameters(int interval, int maxload) +{ + m_interval = interval; + m_maxload = maxload; + + if (m_interval < 0) { + m_interval = 0; + } + if (m_maxload < 1) { + m_maxload = 1; + } else if (m_maxload > 100) { + m_maxload = 100; + } +} + +void PollingScheduler::reset() +{ + m_initialState = true; +} + +void PollingScheduler::newPass() +{ + TimeMillis timeNow; + + if (m_initialState) { + + // First polling pass: initialize statistics. + m_initialState = false; + m_ratedDuration = 0; + m_sleeping = 0; + memset(m_errors, 0, sizeof(m_errors)); + m_errorSum = 0; + m_errorAbsSum = 0; + memset(m_durations, 0, sizeof(m_durations)); + m_durationSum = 0; + memset(m_slept, 0, sizeof(m_slept)); + m_sleptSum = 0; + m_idx = 0; + m_count = 0; + + } else { + + // Stop sleeping if not yet. + if (m_sleeping) + sleepFinished(); + + // Update statistics on sleeping time and total pass duration. + int duration = timeNow.diffFrom(m_passStarted); + + int oldest = m_durations[m_idx]; + m_durations[m_idx] = duration; + m_durationSum = m_durationSum - oldest + duration; + + oldest = m_slept[m_idx]; + m_slept[m_idx] = m_sleptThisPass; + m_sleptSum = m_sleptSum - oldest + m_sleptThisPass; + + // Compute and save the difference between actual and planned time. + int newError = duration - m_interval; + oldest = m_errors[m_idx]; + m_errors[m_idx] = newError; + m_errorSum = m_errorSum - oldest + newError; + m_errorAbsSum = m_errorAbsSum - abs(oldest) + abs(newError); + + // + // Below is the most important part. + // Compute desired duration of the upcoming polling pass. + // + + // Estimation based on keeping up constant interval. + m_ratedDuration = m_interval - m_errorSum / 2; + + // Estimations based on keeping up desired CPU load. + int optimalLoadDuration1 = 0; + int optimalLoadDuration8 = 0; + int optimalLoadDuration = 0; + + if (m_count > 4) { + // Estimation 1 (use previous pass statistics). + optimalLoadDuration1 = + ((duration - m_sleptThisPass) * 100 + m_maxload/2) / m_maxload; + + if (m_count > 16) { + // Estimation 2 (use history of 8 previous passes). + optimalLoadDuration8 = + ((m_durationSum - m_sleptSum) * 900 + m_maxload*4) / (m_maxload*8) + - m_durationSum; + // Mix the above two giving more priority to the first. + optimalLoadDuration = + (2 * optimalLoadDuration1 + optimalLoadDuration8) / 3; + } else { + optimalLoadDuration = optimalLoadDuration1; + } + } + +#ifdef DEBUG + fprintf(stderr, "\t", + m_ratedDuration, optimalLoadDuration1, optimalLoadDuration8); +#endif + + // Choose final estimation. + if (m_ratedDuration < optimalLoadDuration) { + m_ratedDuration = optimalLoadDuration; + } + if (m_ratedDuration < 0) { + m_ratedDuration = 0; + } else if (m_ratedDuration > 500 && m_interval <= 100) { + m_ratedDuration = 500; + } else if (m_ratedDuration > 1000) { + m_ratedDuration = 1000; + } + +#ifdef DEBUG + fprintf(stderr, "\t", m_ratedDuration); +#endif + + // Update ring buffer indexer (8 elements per each arrays). + m_idx = (m_idx + 1) & 7; + + // Update pass counter. + m_count++; + + } + + m_passStarted = timeNow; + m_sleptThisPass = 0; +} + +void PollingScheduler::sleepStarted() +{ + if (m_initialState || m_sleeping) + return; + + m_sleepStarted.update(); + + m_sleeping = true; +} + +void PollingScheduler::sleepFinished() +{ + if (m_initialState || !m_sleeping) + return; + + TimeMillis timeNow; + m_sleptThisPass += timeNow.diffFrom(m_sleepStarted); + + m_sleeping = false; +} + +int PollingScheduler::millisRemaining() const +{ + if (m_initialState) + return 0; + + TimeMillis timeNow; + int elapsed = timeNow.diffFrom(m_passStarted); + + if (elapsed > m_ratedDuration) + return 0; + + return (m_ratedDuration - elapsed); +} + +bool PollingScheduler::goodTimeToPoll() const +{ + if (m_initialState) + return true; + + // Average error (per 8 elements in the ring buffer). + int errorAvg = (m_errorAbsSum + 4) / 8; + + // It's ok to poll earlier if new error is no more than half-average. + return (millisRemaining() <= errorAvg / 2); +} diff --git a/unix/x0vncserver/PollingScheduler.h b/unix/x0vncserver/PollingScheduler.h new file mode 100644 index 00000000..2e3e5be7 --- /dev/null +++ b/unix/x0vncserver/PollingScheduler.h @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 Constantin Kaplinsky. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// PollingScheduler class. It is used for deciding when to start new +// polling pass, and how much time it is ok to sleep before starting. +// PollingScheduler is given a desired polling interval, but it can +// add time between polling passes if needed for satisfying processor +// usage limitation. +// + +#ifndef __POLLINGSCHEDULER_H__ +#define __POLLINGSCHEDULER_H__ + +#include + +class PollingScheduler { + +public: + + PollingScheduler(int interval, int maxload = 50); + + // Set polling parameters. + void setParameters(int interval, int maxload = 50); + + // Reset the object into the initial state (no polling performed). + void reset(); + + // Tell the scheduler that new polling pass is just being started. + void newPass(); + + // Inform the scheduler about times when we sleep. + void sleepStarted(); + void sleepFinished(); + + // This function estimates time remaining before new polling pass. + int millisRemaining() const; + + // This function tells if it's ok to start polling pass right now. + bool goodTimeToPoll() const; + +protected: + + // Parameters. + int m_interval; + int m_maxload; + + // This boolean flag is true when we do not poll the screen. + bool m_initialState; + + // Time stamp saved on starting current polling pass. + TimeMillis m_passStarted; + + // Desired duration of current polling pass. + int m_ratedDuration; + + // These are for measuring sleep time in current pass. + TimeMillis m_sleepStarted; + bool m_sleeping; + int m_sleptThisPass; + + // Ring buffer for tracking past timing errors. + int m_errors[8]; + int m_errorSum; + int m_errorAbsSum; + + // Ring buffer for tracking total pass durations (work + sleep). + int m_durations[8]; + int m_durationSum; + + // Ring buffer for tracking past sleep times. + int m_slept[8]; + int m_sleptSum; + + // Indexer for all ring buffers. + int m_idx; + + // Pass counter. + int m_count; +}; + +#endif // __POLLINGSCHEDULER_H__ + diff --git a/unix/x0vncserver/TimeMillis.cxx b/unix/x0vncserver/TimeMillis.cxx new file mode 100644 index 00000000..059c043b --- /dev/null +++ b/unix/x0vncserver/TimeMillis.cxx @@ -0,0 +1,49 @@ +/* Copyright (C) 2006 Constantin Kaplinsky. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// TimeMillis.cxx +// + +#include + +// XXX Lynx/OS 2.3: get proto for gettimeofday() +#ifdef Lynx +#include +#endif + +TimeMillis::TimeMillis() +{ + update(); +} + +bool TimeMillis::update() +{ + struct timezone tz; + return (gettimeofday(&m_timeval, &tz) == 0); +} + +int TimeMillis::diffFrom(const TimeMillis &older) const +{ + int diff = (int) + ((m_timeval.tv_usec - older.m_timeval.tv_usec + 500) / 1000 + + (m_timeval.tv_sec - older.m_timeval.tv_sec) * 1000); + + return diff; +} + diff --git a/unix/x0vncserver/TimeMillis.h b/unix/x0vncserver/TimeMillis.h new file mode 100644 index 00000000..e79db12c --- /dev/null +++ b/unix/x0vncserver/TimeMillis.h @@ -0,0 +1,47 @@ +/* Copyright (C) 2006 Constantin Kaplinsky. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// +// TimeMillis.h +// + +#ifndef __TIMEMILLIS_H__ +#define __TIMEMILLIS_H__ + +#include + +class TimeMillis { + +public: + + TimeMillis(); + + // Set this object to current time, returns true on sucess. + bool update(); + + // Return difference in milliseconds between two time points. + int diffFrom(const TimeMillis &older) const; + +protected: + + struct timeval m_timeval; + +}; + +#endif // __TIMEMILLIS_H__ + diff --git a/unix/x0vncserver/buildtime.c b/unix/x0vncserver/buildtime.c new file mode 100644 index 00000000..a96031cc --- /dev/null +++ b/unix/x0vncserver/buildtime.c @@ -0,0 +1,18 @@ +/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +char buildtime[] = __DATE__ " " __TIME__; diff --git a/unix/x0vncserver/x0vncserver.cxx b/unix/x0vncserver/x0vncserver.cxx new file mode 100644 index 00000000..80483bf8 --- /dev/null +++ b/unix/x0vncserver/x0vncserver.cxx @@ -0,0 +1,580 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2004-2006 Constantin Kaplinsky. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +// FIXME: Check cases when screen width/height is not a multiply of 32. +// e.g. 800x600. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#ifdef HAVE_XTEST +#include +#endif + +#include +#include +#include +#include + +// XXX Lynx/OS 2.3: protos for select(), bzero() +#ifdef Lynx +#include +#endif + +using namespace rfb; +using namespace network; + +static LogWriter vlog("Main"); + +IntParameter pollingCycle("PollingCycle", "Milliseconds per one polling " + "cycle; actual interval may be dynamically " + "adjusted to satisfy MaxProcessorUsage setting", 30); +IntParameter maxProcessorUsage("MaxProcessorUsage", "Maximum percentage of " + "CPU time to be consumed", 35); +BoolParameter useShm("UseSHM", "Use MIT-SHM extension if available", true); +BoolParameter useOverlay("OverlayMode", "Use overlay mode under " + "IRIX or Solaris", true); +StringParameter displayname("display", "The X display", ""); +IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",5900); +IntParameter queryConnectTimeout("QueryConnectTimeout", + "Number of seconds to show the Accept Connection dialog before " + "rejecting the connection", + 10); +StringParameter hostsFile("HostsFile", "File with IP access control rules", ""); + +// +// Allow the main loop terminate itself gracefully on receiving a signal. +// + +static bool caughtSignal = false; + +static void CleanupSignalHandler(int sig) +{ + caughtSignal = true; +} + + +class QueryConnHandler : public VNCServerST::QueryConnectionHandler, + public QueryResultCallback { +public: + QueryConnHandler(Display* dpy, VNCServerST* vs) + : display(dpy), server(vs), queryConnectDialog(0), queryConnectSock(0) {} + ~QueryConnHandler() { delete queryConnectDialog; } + + // -=- VNCServerST::QueryConnectionHandler interface + virtual VNCServerST::queryResult queryConnection(network::Socket* sock, + const char* userName, + char** reason) { + if (queryConnectSock) { + *reason = strDup("Another connection is currently being queried."); + return VNCServerST::REJECT; + } + if (!userName) userName = "(anonymous)"; + queryConnectSock = sock; + CharArray address(sock->getPeerAddress()); + delete queryConnectDialog; + queryConnectDialog = new QueryConnectDialog(display, address.buf, + userName, queryConnectTimeout, + this); + queryConnectDialog->map(); + return VNCServerST::PENDING; + } + + // -=- QueryResultCallback interface + virtual void queryApproved() { + server->approveConnection(queryConnectSock, true, 0); + queryConnectSock = 0; + } + virtual void queryRejected() { + server->approveConnection(queryConnectSock, false, + "Connection rejected by local user"); + queryConnectSock = 0; + } +private: + Display* display; + VNCServerST* server; + QueryConnectDialog* queryConnectDialog; + network::Socket* queryConnectSock; +}; + + +// +// XPixelBuffer is a modification of FullFramePixelBuffer that does +// not always return buffer width in getStride(). +// + +class XPixelBuffer : public FullFramePixelBuffer +{ +public: + XPixelBuffer(const PixelFormat& pf, int width, int height, + rdr::U8* data_, ColourMap* cm, int stride_) : + FullFramePixelBuffer(pf, width, height, data_, cm), stride(stride_) + { + } + + virtual int getStride() const { return stride; } + +protected: + int stride; +}; + + +class XDesktop : public SDesktop, public ColourMap +{ +public: + XDesktop(Display* dpy_, Geometry *geometry_) + : dpy(dpy_), geometry(geometry_), pb(0), server(0), image(0), pollmgr(0), + oldButtonMask(0), haveXtest(false), maxButtons(0), running(false) + { +#ifdef HAVE_XTEST + int xtestEventBase; + int xtestErrorBase; + int major, minor; + + if (XTestQueryExtension(dpy, &xtestEventBase, + &xtestErrorBase, &major, &minor)) { + XTestGrabControl(dpy, True); + vlog.info("XTest extension present - version %d.%d",major,minor); + haveXtest = true; + } else { +#endif + vlog.info("XTest extension not present"); + vlog.info("Unable to inject events or display while server is grabbed"); +#ifdef HAVE_XTEST + } +#endif + + } + virtual ~XDesktop() { + stop(); + } + + // -=- SDesktop interface + + virtual void start(VNCServer* vs) { + + // Determine actual number of buttons of the X pointer device. + unsigned char btnMap[8]; + int numButtons = XGetPointerMapping(dpy, btnMap, 8); + maxButtons = (numButtons > 8) ? 8 : numButtons; + vlog.info("Enabling %d button%s of X pointer device", + maxButtons, (maxButtons != 1) ? "s" : ""); + + // Create an image for maintaining framebuffer data. + ImageFactory factory((bool)useShm, (bool)useOverlay); + image = factory.newImage(dpy, geometry->width(), geometry->height()); + vlog.info("Allocated %s", image->classDesc()); + + // Create polling manager object. It will track screen changes and + // keep pixels of the `image' object up to date. + pollmgr = new PollingManager(dpy, image, &factory, + geometry->offsetLeft(), + geometry->offsetTop()); + pollmgr->setVNCServer(vs); + + pf.bpp = image->xim->bits_per_pixel; + pf.depth = image->xim->depth; + pf.bigEndian = (image->xim->byte_order == MSBFirst); + pf.trueColour = image->isTrueColor(); + pf.redShift = ffs(image->xim->red_mask) - 1; + pf.greenShift = ffs(image->xim->green_mask) - 1; + pf.blueShift = ffs(image->xim->blue_mask) - 1; + pf.redMax = image->xim->red_mask >> pf.redShift; + pf.greenMax = image->xim->green_mask >> pf.greenShift; + pf.blueMax = image->xim->blue_mask >> pf.blueShift; + + // Calculate the number of pixels in a row, with padding included. + int stride = image->xim->bytes_per_line * 8 / image->xim->bits_per_pixel; + + // Provide pixel buffer to the server object. + pb = new XPixelBuffer(pf, geometry->width(), geometry->height(), + (rdr::U8*)image->xim->data, this, stride); + server = vs; + server->setPixelBuffer(pb); + + running = true; + } + + virtual void stop() { + running = false; + + delete pb; + delete pollmgr; + delete image; + + pb = 0; + pollmgr = 0; + image = 0; + } + + inline bool isRunning() { + return running; + } + + inline void poll() { + if (pollmgr) + pollmgr->poll(); + } + + virtual void pointerEvent(const Point& pos, int buttonMask) { + pollmgr->setPointerPos(pos); +#ifdef HAVE_XTEST + if (!haveXtest) return; + XTestFakeMotionEvent(dpy, DefaultScreen(dpy), + geometry->offsetLeft() + pos.x, + geometry->offsetTop() + pos.y, + CurrentTime); + if (buttonMask != oldButtonMask) { + for (int i = 0; i < maxButtons; i++) { + if ((buttonMask ^ oldButtonMask) & (1<width(), pb->height()); + } + + // -=- ColourMap callbacks + virtual void lookup(int index, int* r, int* g, int* b) { + XColor xc; + xc.pixel = index; + if (index < DisplayCells(dpy,DefaultScreen(dpy))) { + XQueryColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), &xc); + } else { + xc.red = xc.green = xc.blue = 0; + } + *r = xc.red; + *g = xc.green; + *b = xc.blue; + } + +protected: + Display* dpy; + Geometry* geometry; + PixelFormat pf; + PixelBuffer* pb; + VNCServer* server; + Image* image; + PollingManager* pollmgr; + int oldButtonMask; + bool haveXtest; + int maxButtons; + bool running; +}; + + +class FileTcpFilter : public TcpFilter +{ + +public: + + FileTcpFilter(const char *fname) + : TcpFilter("-"), fileName(NULL), lastModTime(0) + { + if (fname != NULL) + fileName = strdup((char *)fname); + } + + virtual ~FileTcpFilter() + { + if (fileName != NULL) + free(fileName); + } + + virtual bool verifyConnection(Socket* s) + { + if (!reloadRules()) { + vlog.error("Could not read IP filtering rules: rejecting all clients"); + filter.clear(); + filter.push_back(parsePattern("-")); + return false; + } + + return TcpFilter::verifyConnection(s); + } + +protected: + + bool reloadRules() + { + if (fileName == NULL) + return true; + + struct stat st; + if (stat(fileName, &st) != 0) + return false; + + if (st.st_mtime != lastModTime) { + // Actually reload only if the file was modified + FILE *fp = fopen(fileName, "r"); + if (fp == NULL) + return false; + + // Remove all the rules from the parent class + filter.clear(); + + // Parse the file contents adding rules to the parent class + char buf[32]; + while (readLine(buf, 32, fp)) { + if (buf[0] && strchr("+-?", buf[0])) { + filter.push_back(parsePattern(buf)); + } + } + + fclose(fp); + lastModTime = st.st_mtime; + } + return true; + } + +protected: + + char *fileName; + time_t lastModTime; + +private: + + // + // NOTE: we silently truncate long lines in this function. + // + + bool readLine(char *buf, int bufSize, FILE *fp) + { + if (fp == NULL || buf == NULL || bufSize == 0) + return false; + + if (fgets(buf, bufSize, fp) == NULL) + return false; + + char *ptr = strchr(buf, '\n'); + if (ptr != NULL) { + *ptr = '\0'; // remove newline at the end + } else { + if (!feof(fp)) { + int c; + do { // skip the rest of a long line + c = getc(fp); + } while (c != '\n' && c != EOF); + } + } + return true; + } + +}; + +char* programName; + +static void usage() +{ + fprintf(stderr, "\nusage: %s []\n", programName); + fprintf(stderr,"\n" + "Parameters can be turned on with - or off with -=0\n" + "Parameters which take a value can be specified as " + "- \n" + "Other valid forms are = -= " + "--=\n" + "Parameter names are case-insensitive. The parameters are:\n\n"); + Configuration::listParams(79, 14); + exit(1); +} + +int main(int argc, char** argv) +{ + initStdIOLoggers(); + LogWriter::setLogParams("*:stderr:30"); + + programName = argv[0]; + Display* dpy; + + for (int i = 1; i < argc; i++) { + if (Configuration::setParam(argv[i])) + continue; + + if (argv[i][0] == '-') { + if (i+1 < argc) { + if (Configuration::setParam(&argv[i][1], argv[i+1])) { + i++; + continue; + } + } + usage(); + } + + usage(); + } + + CharArray dpyStr(displayname.getData()); + if (!(dpy = XOpenDisplay(dpyStr.buf[0] ? dpyStr.buf : 0))) { + fprintf(stderr,"%s: unable to open display \"%s\"\r\n", + programName, XDisplayName(displayname.getData())); + exit(1); + } + + signal(SIGHUP, CleanupSignalHandler); + signal(SIGINT, CleanupSignalHandler); + signal(SIGTERM, CleanupSignalHandler); + + try { + TXWindow::init(dpy,"x0vncserver"); + Geometry geo(DisplayWidth(dpy, DefaultScreen(dpy)), + DisplayHeight(dpy, DefaultScreen(dpy))); + XDesktop desktop(dpy, &geo); + VNCServerST server("x0vncserver", &desktop); + QueryConnHandler qcHandler(dpy, &server); + server.setQueryConnectionHandler(&qcHandler); + + TcpListener listener((int)rfbport); + vlog.info("Listening on port %d", (int)rfbport); + + FileTcpFilter fileTcpFilter(hostsFile.getData()); + if (strlen(hostsFile.getData()) != 0) + listener.setFilter(&fileTcpFilter); + + PollingScheduler sched((int)pollingCycle, (int)maxProcessorUsage); + + while (!caughtSignal) { + struct timeval tv; + fd_set rfds; + std::list sockets; + std::list::iterator i; + + // Process any incoming X events + TXWindow::handleXEvents(dpy); + + FD_ZERO(&rfds); + FD_SET(listener.getFd(), &rfds); + server.getSockets(&sockets); + int clients_connected = 0; + for (i = sockets.begin(); i != sockets.end(); i++) { + if ((*i)->isShutdown()) { + server.removeSocket(*i); + delete (*i); + } else { + FD_SET((*i)->getFd(), &rfds); + clients_connected++; + } + } + + if (clients_connected) { + int wait_ms = sched.millisRemaining(); + if (wait_ms > 500) { + wait_ms = 500; + } + tv.tv_usec = wait_ms * 1000; +#ifdef DEBUG + // fprintf(stderr, "[%d]\t", wait_ms); +#endif + } else { + sched.reset(); + tv.tv_usec = 100000; + } + tv.tv_sec = 0; + + // Do the wait... + sched.sleepStarted(); + int n = select(FD_SETSIZE, &rfds, 0, 0, &tv); + sched.sleepFinished(); + + if (n < 0) { + if (errno == EINTR) { + vlog.debug("Interrupted select() system call"); + continue; + } else { + throw rdr::SystemException("select", errno); + } + } + + // Accept new VNC connections + if (FD_ISSET(listener.getFd(), &rfds)) { + Socket* sock = listener.accept(); + if (sock) { + server.addSocket(sock); + } else { + vlog.status("Client connection rejected"); + } + } + + Timer::checkTimeouts(); + server.checkTimeouts(); + + // Client list could have been changed. + server.getSockets(&sockets); + + // Nothing more to do if there are no client connections. + if (sockets.empty()) + continue; + + // Process events on existing VNC connections + for (i = sockets.begin(); i != sockets.end(); i++) { + if (FD_ISSET((*i)->getFd(), &rfds)) + server.processSocketEvent(*i); + } + + if (desktop.isRunning() && sched.goodTimeToPoll()) { + sched.newPass(); + desktop.poll(); + } + } + + } catch (rdr::Exception &e) { + vlog.error(e.str()); + return 1; + } + + vlog.info("Terminated"); + return 0; +} diff --git a/unix/x0vncserver/x0vncserver.man b/unix/x0vncserver/x0vncserver.man new file mode 100644 index 00000000..da9ba944 --- /dev/null +++ b/unix/x0vncserver/x0vncserver.man @@ -0,0 +1,33 @@ +.TH x0vncserver 1 "17 Apr 2006" "TightVNC" "Virtual Network Computing" +.SH NAME +x0vncserver \- VNC server which continuously polls an X display +.SH SYNOPSIS +.B x0vncserver +[\fIparameters\fP] +.SH DESCRIPTION +.B x0vncserver +is a VNC server which continuously polls any X display, allowing it to be +controlled via VNC. How usable it will be depends a lot on the machine it's +running on, and what you're expecting. It won't be as fast as Xvnc or a native +X server with VNC support compiled in, but in many cases it is the best option +since it is just an ordinary X application requiring no special installation. + +It has many of the same parameters as Xvnc. Running \fBx0vncserver -h\fP will +give a list of parameters with descriptions. Note that you need to explicitly +specify an appropriate password file using the PasswordFile parameter. + +.SH SEE ALSO +.BR Xvnc (1) +.BR vncpasswd (1), +.BR vncviewer (1), +.BR vncserver (1), +.br +http://www.tightvnc.com + +.SH AUTHOR +Tristan Richardson, RealVNC Ltd. + +VNC was originally developed by the RealVNC team while at Olivetti +Research Ltd / AT&T Laboratories Cambridge. TightVNC additions was +implemented by Constantin Kaplinsky. Many other people participated in +development, testing and support. diff --git a/unix/xc.patch b/unix/xc.patch new file mode 100644 index 00000000..a5927b95 --- /dev/null +++ b/unix/xc.patch @@ -0,0 +1,67 @@ +diff -bcr xc.org/programs/Xserver/Imakefile xc/programs/Xserver/Imakefile +*** xc.org/programs/Xserver/Imakefile 2004-12-15 20:22:53.000000000 +0100 +--- xc/programs/Xserver/Imakefile 2005-02-14 14:23:21.000000000 +0100 +*************** +*** 128,134 **** + LIBREGEX = RegexLibrary + + #if DoLoadableServer +! LIBCWRAPPER = os/libcwrapper.o + #endif + + #if BuildXprint +--- 128,134 ---- + LIBREGEX = RegexLibrary + + #if DoLoadableServer +! LIBCWRAPPER = os/libcwrapper.o os/libos.a + #endif + + #if BuildXprint +*************** +*** 414,419 **** +--- 414,430 ---- + #define ServerToInstall Xsun + #endif + #endif /* XsunServer */ ++ XCOMM ++ XCOMM X VNC server ++ XCOMM ++ FBSUBDIR = fb ++ XVNCDDXDIR = vnc/Xvnc ++ XVNCDIRS = $(STDDIRS) $(FBSUBDIR) miext/damage $(XVNCDDXDIR) $(DEPDIRS) ++ XVNCLIBS = PreFbLibs vnc/Xvnc/LibraryTargetName(xvnc) FbPostFbLibs ++ XVNCOBJS = $(XVNCDDXDIR)/stubs.o $(XVNCDDXDIR)/miinitext.o ++ XVNCSYSLIBS = $(FONTLIBS) $(SYSLIBS) ++ ServerTarget(Xvnc,$(XVNCDIRS),$(XVNCOBJS), \ ++ $(LIBCWRAPPER) $(XVNCLIBS) $(LOADABLEEXTS),$(XVNCSYSLIBS)) + + + #if defined(Xsun24Server) && Xsun24Server +diff -bcr xc.org/programs/Xserver/mi/miinitext.c xc/programs/Xserver/mi/miinitext.c +*** xc.org/programs/Xserver/mi/miinitext.c 2004-12-13 06:48:41.000000000 +0100 +--- xc/programs/Xserver/mi/miinitext.c 2005-02-11 16:47:34.000000000 +0100 +*************** +*** 286,291 **** +--- 286,294 ---- + #ifdef MITMISC + extern void MITMiscExtensionInit(INITARGS); + #endif ++ #ifdef VNCEXT ++ extern void vncExtensionInit(INITARGS); ++ #endif + #ifdef XIDLE + extern void XIdleExtensionInit(INITARGS); + #endif +*************** +*** 587,592 **** +--- 590,598 ---- + #ifdef MITMISC + if (!noMITMiscExtension) MITMiscExtensionInit(); + #endif ++ #ifdef VNCEXT ++ vncExtensionInit(); ++ #endif + #ifdef XIDLE + if (!noXIdleExtension) XIdleExtensionInit(); + #endif diff --git a/unix/xc/config/cf/host.def b/unix/xc/config/cf/host.def new file mode 100644 index 00000000..2de89af0 --- /dev/null +++ b/unix/xc/config/cf/host.def @@ -0,0 +1 @@ +#include diff --git a/unix/xc/config/cf/vnc.def b/unix/xc/config/cf/vnc.def new file mode 100644 index 00000000..c933f4dc --- /dev/null +++ b/unix/xc/config/cf/vnc.def @@ -0,0 +1,36 @@ +#define BuildServersOnly YES +#define BuildFonts NO +#define BuildClients NO +#define BuildDocs NO +#define BuildPexExt NO +#define BuildNls NO +#define BuildXIE NO +#define BuildGlxExt YES +#define GlxBuiltInXMesa YES +#define XnestServer YES +#define XF86Server NO +#define XprtServer NO +#define BuildXFree86ConfigTools NO + +#ifdef SunArchitecture +#define ProjectRoot /usr/openwin +#define HasGcc3 YES +#endif + +#define HasFreetype2 NO +#define BuildVNCExt YES +#define VNCExtDefines -DVNCEXT +#define SiteExtensionDefines VNCExtDefines +#define SiteExtensionDirs vnc + +#define VncExtLibs $(TOP)/../rfb/librfb.a \ + $(TOP)/../Xregion/libXregion.a \ + $(TOP)/../network/libnetwork.a \ + $(TOP)/../rdr/librdr.a \ + $(TOP)/../jpeg/build/libjpeg.a + +#define SiteExtensionLibs vnc/LibraryTargetName(vnc) VncExtLibs + +#define ServerTarget(server,subdirs,objects,libs,syslibs) @@\ +CCLINK = $(CXXENVSETUP) $(CXX) @@\ +ServerTargetWithFlags(server,subdirs,objects,libs,syslibs,$(_NOOP_)) diff --git a/unix/xc/programs/Xserver/Xvnc.man b/unix/xc/programs/Xserver/Xvnc.man new file mode 100644 index 00000000..128bc937 --- /dev/null +++ b/unix/xc/programs/Xserver/Xvnc.man @@ -0,0 +1,284 @@ +.TH Xvnc 1 "17 Apr 2006" "TightVNC" "Virtual Network Computing" +.SH NAME +Xvnc \- the X VNC server +.SH SYNOPSIS +.B Xvnc +.RI [ options ] +.RI : display# +.SH DESCRIPTION +.B Xvnc +is the X VNC (Virtual Network Computing) server. It is based on a standard X +server, but it has a "virtual" screen rather than a physical one. X +applications display themselves on it as if it were a normal X display, but +they can only be accessed via a VNC viewer - see \fBvncviewer\fP(1). + +So Xvnc is really two servers in one. To the applications it is an X server, +and to the remote VNC users it is a VNC server. By convention we have arranged +that the VNC server display number will be the same as the X server display +number, which means you can use eg. snoopy:2 to refer to display 2 on machine +"snoopy" in both the X world and the VNC world. + +The best way of starting \fBXvnc\fP is via the \fBvncserver\fP script. This +sets up the environment appropriately and runs some X applications to get you +going. See the manual page for \fBvncserver\fP(1) for more information. + +.SH OPTIONS +.B Xvnc +takes lots of options - running \fBXvnc -help\fP gives a list. Many of these +are standard X server options, which are described in the \fBXserver\fP(1) +manual page. In addition to options which can only be set via the +command-line, there are also "parameters" which can be set both via the +command-line and through the \fBvncconfig\fP(1) program. + +.TP +.B \-geometry \fIwidth\fPx\fIheight\fP +Specify the size of the desktop to be created. Default is 1024x768. + +.TP +.B \-depth \fIdepth\fP +Specify the pixel depth in bits of the desktop to be created. Default is 16, +other possible values are 8, 15, and 24 - anything else is likely to cause +strange behaviour by applications. + +.TP +.B \-pixelformat \fIformat\fP +Specify pixel format for server to use (BGRnnn or RGBnnn). The default for +depth 8 is BGR233 (meaning the most significant two bits represent blue, the +next three green, and the least significant three represent red), the default +for depth 16 is RGB565 and for depth 24 is RGB888. + +.TP +.B \-cc 3 +As an alternative to the default TrueColor visual, this allows you to run an +Xvnc server with a PseudoColor visual (i.e. one which uses a color map or +palette), which can be useful for running some old X applications which only +work on such a display. Values other than 3 (PseudoColor) and 4 (TrueColor) +for the \-cc option may result in strange behaviour, and PseudoColor desktops +must be 8 bits deep (i.e. \fB-depth 8\fP). + +.TP +.B \-inetd +This significantly changes Xvnc's behaviour so that it can be launched from +inetd. See the section below on usage with inetd. + +.TP +.B \-help +List all the options and parameters + +.SH PARAMETERS +VNC parameters can be set both via the command-line and through the +\fBvncconfig\fP(1) program, and with a VNC-enabled XFree86 server via Options +entries in the XF86Config file. + +Parameters can be turned on with -\fIparam\fP or off with +-\fIparam\fP=0. Parameters which take a value can be specified as +-\fIparam\fP \fIvalue\fP. Other valid forms are \fIparam\fP\fB=\fP\fIvalue\fP +-\fIparam\fP=\fIvalue\fP --\fIparam\fP=\fIvalue\fP. Parameter names are +case-insensitive. + +.TP +.B \-desktop \fIdesktop-name\fP +Each desktop has a name which may be displayed by the viewer. It defaults to +"x11". + +.TP +.B \-rfbport \fIport\fP +Specifies the TCP port on which Xvnc listens for connections from viewers (the +protocol used in VNC is called RFB - "remote framebuffer"). The default is +5900 plus the display number. + +.TP +.B \-rfbwait \fItime\fP, \-ClientWaitTimeMillis \fItime\fP + +Time in milliseconds to wait for a viewer which is blocking Xvnc. This is +necessary because Xvnc is single-threaded and sometimes blocks until the viewer +has finished sending or receiving a message - note that this does not mean an +update will be aborted after this time. Default is 20000 (20 seconds). + +.TP +.B \-httpd \fIdirectory\fP +Run a mini-HTTP server which serves files from the given directory. Normally +the directory will contain the classes for the Java viewer. In addition, files +with a .vnc extension will have certain substitutions made so that a single +installation of the Java VNC viewer can be served by separate instances of +Xvnc. + +.TP +.B \-httpPort \fIport\fP +Specifies the port on which the mini-HTTP server runs. Default is 5800 plus +the display number. + +.TP +.B \-rfbauth \fIpasswd-file\fP, \-PasswordFile \fIpasswd-file\fP +Specifies the file containing the password used to authenticate viewers. The +file is accessed each time a connection comes in, so it can be changed on the +fly via \fBvncpasswd\fP(1). + +.TP +.B \-deferUpdate \fItime\fP +Xvnc uses a "deferred update" mechanism which enhances performance in many +cases. After any change to the framebuffer, Xvnc waits for this number of +milliseconds (default 40) before sending an update to any waiting clients. This +means that more changes tend to get coalesced together in a single +update. Setting it to 0 results in the same behaviour as earlier versions of +Xvnc, where the first change to the framebuffer causes an immediate update to +any waiting clients. + +.TP +.B \-SendCutText +Send clipboard changes to clients (default is on). Note that you must also run +\fBvncconfig\fP(1) to get the clipboard to work. + +.TP +.B \-AcceptCutText +Accept clipboard updates from clients (default is on). Note that you must also +run \fBvncconfig\fP(1) to get the clipboard to work. + +.TP +.B \-AcceptPointerEvents +Accept pointer press and release events from clients (default is on). + +.TP +.B \-AcceptKeyEvents +Accept key press and release events from clients (default is on). + +.TP +.B \-DisconnectClients +Disconnect existing clients if an incoming connection is non-shared (default is +on). If \fBDisconnectClients\fP is false, then a new non-shared connection will +be refused while there is a client active. When combined with +\fBNeverShared\fP this means only one client is allowed at a time. + +.TP +.B \-NeverShared +Never treat incoming connections as shared, regardless of the client-specified +setting (default is off). + +.TP +.B \-AlwaysShared +Always treat incoming connections as shared, regardless of the client-specified +setting (default is off). + +.TP +.B \-Protocol3.3 +Always use protocol version 3.3 for backwards compatibility with badly-behaved +clients (default is off). + +.TP +.B \-CompareFB +Perform pixel comparison on framebuffer to reduce unnecessary updates (default +is on). + +.TP +.B \-SecurityTypes \fIsec-types\fP +Specify which security schemes to use separated by commas. At present only +"None" and "VncAuth" are supported. The default is "VncAuth" - note that if +you want a server which does not require a password, you must set this +parameter to "None". + +.TP +.B \-IdleTimeout \fIseconds\fP +The number of seconds after which an idle VNC connection will be dropped +(default is 0, which means that idle connections will never be dropped). + +.TP +.B \-QueryConnect +Prompts the user of the desktop to explicitly accept or reject incoming +connections. This is most useful when using the vnc.so module or +\fBx0vncserver\fP(1) program to access an existing X desktop via VNC. + +The \fBvncconfig\fP(1) program must be running on the desktop in order for +QueryConnect to be supported by the \fBvnc.so\fP(1) module or +\fBXvnc\fP(1) program. The \fBx0vncserver\fP(1) program does not require +\fBvncconfig\fP(1) to be running. + +.TP +.B \-localhost +Only allow connections from the same machine. Useful if you use SSH and want to +stop non-SSH connections from any other hosts. See the guide to using VNC with +SSH on the web site. + +.TP +.B \-log \fIlogname\fP:\fIdest\fP:\fIlevel\fP +Configures the debug log settings. \fIdest\fP can currently be \fBstderr\fP or +\fBstdout\fP, and \fIlevel\fP is between 0 and 100, 100 meaning most verbose +output. \fIlogname\fP is usually \fB*\fP meaning all, but you can target a +specific source file if you know the name of its "LogWriter". Default is +\fB*:stderr:30\fP. + +.TP +.B \-RemapKeys \fImapping +Sets up a keyboard mapping. +.I mapping +is a comma-separated string of character mappings, each of the form +.IR char -> char , +or +.IR char <> char , +where +.I char +is a hexadecimal keysym. For example, to exchange the " and @ symbols you would specify the following: +.IP "" 10 +RemapKeys=0x22<>0x40 + +.SH USAGE WITH INETD +By configuring the \fBinetd\fP(1) service appropriately, Xvnc can be launched +on demand when a connection comes in, rather than having to be started +manually. When given the \fB-inetd\fP option, instead of listening for TCP +connections on a given port it uses its standard input and standard output. +There are two modes controlled by the wait/nowait entry in the inetd.conf file. + +In the nowait mode, Xvnc uses its standard input and output directly as the +connection to a viewer. It never has a listening socket, so cannot accept +further connections from viewers (it can however connect out to listening +viewers by use of the vncconfig program). Further viewer connections to the +same TCP port result in inetd spawning off a new Xvnc to deal with each +connection. When the connection to the viewer dies, the Xvnc and any +associated X clients die. This behaviour is most useful when combined with the +XDMCP options -query and -once. An typical example in inetd.conf might be (all +on one line): + +5950 stream tcp nowait nobody /usr/local/bin/Xvnc Xvnc -inetd -query +localhost -once securitytypes=none + +In this example a viewer connection to :50 will result in a new Xvnc for that +connection which should display the standard XDM login screen on that machine. +Because the user needs to login via XDM, it is usually OK to accept connections +without a VNC password in this case. + +In the wait mode, when the first connection comes in, inetd gives the listening +socket to Xvnc. This means that for a given TCP port, there is only ever one +Xvnc at a time. Further viewer connections to the same port are accepted by +the same Xvnc in the normal way. Even when the original connection is broken, +the Xvnc will continue to run. If this is used with the XDMCP options -query +and -once, the Xvnc and associated X clients will die when the user logs out of +the X session in the normal way. It is important to use a VNC password in this +case. A typical entry in inetd.conf might be: + +5951 stream tcp wait james /usr/local/bin/Xvnc Xvnc -inetd -query localhost -once passwordFile=/home/james/.vnc/passwd + +In fact typically, you would have one entry for each user who uses VNC +regularly, each of whom has their own dedicated TCP port which they use. In +this example, when user "james" connects to :51, he enters his VNC password, +then gets the XDM login screen where he logs in in the normal way. However, +unlike the previous example, if he disconnects, the session remains persistent, +and when he reconnects he will get the same session back again. When he logs +out of the X session, the Xvnc will die, but of course a new one will be +created automatically the next time he connects. + +.SH SEE ALSO +.BR vncconfig (1), +.BR vncpasswd (1), +.BR vncserver (1), +.BR vncviewer (1), +.BR Xserver (1), +.BR inetd (1) +.br +http://www.tightvnc.com + +.SH AUTHOR +Tristan Richardson, RealVNC Ltd. + +VNC was originally developed by the RealVNC team while at Olivetti +Research Ltd / AT&T Laboratories Cambridge. TightVNC additions was +implemented by Constantin Kaplinsky. Many other people participated in +development, testing and support. diff --git a/unix/xc/programs/Xserver/vnc/Imakefile b/unix/xc/programs/Xserver/vnc/Imakefile new file mode 100644 index 00000000..1c8132d9 --- /dev/null +++ b/unix/xc/programs/Xserver/vnc/Imakefile @@ -0,0 +1,44 @@ +XCOMM CDEBUGFLAGS = -g +XCOMM CXXDEBUGFLAGS = -g + + VNCTOP = $(TOP)/.. + VNCINCLUDE = -I$(VNCTOP) -I$(VNCTOP)/vncconfig_unix + +#define CplusplusSource + +#if DoLoadableServer +#define IHaveSubdirs +#endif + +#include + +#if DoLoadableServer + MODULE_SUBDIRS = module +#endif + SRCS = vncExtInit.cc vncHooks.cc XserverDesktop.cc + OBJS = vncExtInit.o vncHooks.o XserverDesktop.o + INCLUDES = -I../include -I$(EXTINCSRC) -I$(XINCLUDESRC) -I$(FONTINCSRC) \ + -I../render $(VNCINCLUDE) +#if defined(XFree86Version) && XFree86Version >= 4000 + VNCDEFINES = -DGC_HAS_COMPOSITE_CLIP +#endif +#if defined(ProjectX) && (ProjectX >= 604) + VNCDEFINES = -DGC_HAS_COMPOSITE_CLIP +#endif + DEFINES = $(STD_DEFINES) $(VNCDEFINES) -UXFree86LOADER + +#define IHaveSubdirs +SUBDIRS = Xvnc $(MODULE_SUBDIRS) + +NormalLibraryTarget(vnc,$(OBJS)) +LintLibraryTarget(vnc,$(SRCS)) +NormalLintTarget($(SRCS)) + +NormalLibraryObjectRule() +NormalCplusplusObjectRule() + + +MakeSubdirs($(SUBDIRS)) +DependSubdirs($(SUBDIRS)) + +DependTarget() diff --git a/unix/xc/programs/Xserver/vnc/RegionHelper.h b/unix/xc/programs/Xserver/vnc/RegionHelper.h new file mode 100644 index 00000000..61dc89ff --- /dev/null +++ b/unix/xc/programs/Xserver/vnc/RegionHelper.h @@ -0,0 +1,84 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#ifndef __REGIONHELPER_H__ +#define __REGIONHELPER_H__ + +// RegionHelper is a class which helps in using X server regions by +// automatically freeing them in the destructor. It also fixes a problem with +// REGION_INIT when given an empty rectangle. + +// REGION_NULL was introduced in the Xorg tree as the way to initialise an +// empty region. If it's not already defined do it the old way. Note that the +// old way causes a segfault in the new tree... +#ifndef REGION_NULL +#define REGION_NULL(pScreen,pReg) REGION_INIT(pScreen,pReg,NullBox,0) +#endif + +class RegionHelper { +public: + + // constructor from a single rect + RegionHelper(ScreenPtr pScreen_, BoxPtr rect, int size) + : pScreen(pScreen_), reg(0) + { + init(rect, size); + } + + // constructor from an existing X server region + RegionHelper(ScreenPtr pScreen_, RegionPtr pRegion) + : pScreen(pScreen_), reg(®Rec) + { + REGION_NULL(pScreen, reg); + REGION_COPY(pScreen, reg, pRegion); + } + + // constructor from an array of rectangles + RegionHelper(ScreenPtr pScreen_, int nrects, xRectanglePtr rects, + int ctype=CT_NONE) + : pScreen(pScreen_) + { + reg = RECTS_TO_REGION(pScreen, nrects, rects, ctype); + } + + // constructor for calling init() later + RegionHelper(ScreenPtr pScreen_) : pScreen(pScreen_), reg(0) { + } + + void init(BoxPtr rect, int size) { + reg = ®Rec; + if (!rect || (rect && (rect->x2 == rect->x1 || rect->y2 == rect->y1))) { + REGION_NULL(pScreen, reg); + } else { + REGION_INIT(pScreen, reg, rect, size); + } + } + + // destructor frees as appropriate + ~RegionHelper() { + if (reg == ®Rec) { + REGION_UNINIT(pScreen, reg); + } else if (reg) { + REGION_DESTROY(pScreen, reg); + } + } + ScreenPtr pScreen; + RegionRec regRec; + RegionPtr reg; +}; + +#endif diff --git a/unix/xc/programs/Xserver/vnc/XserverDesktop.cc b/unix/xc/programs/Xserver/vnc/XserverDesktop.cc new file mode 100644 index 00000000..9e5ea0f7 --- /dev/null +++ b/unix/xc/programs/Xserver/vnc/XserverDesktop.cc @@ -0,0 +1,1147 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// XserverDesktop.cxx +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "XserverDesktop.h" +#include "vncExtInit.h" + +extern "C" { +#define public c_public +#define class c_class + + // windowTable is in globals.h in XFree 4, but not in XFree 3 unfortunately +extern WindowPtr *WindowTable; +extern char *display; + +#include "inputstr.h" +#include "servermd.h" +#include "colormapst.h" +#include "resource.h" +#include "cursorstr.h" +#include "windowstr.h" +#define XK_CYRILLIC +#include "keysym.h" +#undef public +#undef class +} + +using namespace rfb; +using namespace network; + +static LogWriter vlog("XserverDesktop"); + +rfb::IntParameter deferUpdateTime("DeferUpdate", + "Time in milliseconds to defer updates",40); + +rfb::BoolParameter alwaysSetDeferUpdateTimer("AlwaysSetDeferUpdateTimer", + "Always reset the defer update timer on every change",false); + +IntParameter queryConnectTimeout("QueryConnectTimeout", + "Number of seconds to show the Accept Connection dialog before " + "rejecting the connection", + 10); + +static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col); + +static rdr::U8 reverseBits[] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, + 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, + 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, + 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, + 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, + 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, + 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, + 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, + 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, + 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, + 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, + 0x3f, 0xbf, 0x7f, 0xff +}; + + +class FileHTTPServer : public rfb::HTTPServer { +public: + FileHTTPServer(XserverDesktop* d) : desktop(d) {} + virtual ~FileHTTPServer() {} + + virtual rdr::InStream* getFile(const char* name, const char** contentType, + int* contentLength, time_t* lastModified) + { + if (name[0] != '/' || strstr(name, "..") != 0) { + vlog.info("http request was for invalid file name"); + return 0; + } + + if (strcmp(name, "/") == 0) name = "/index.vnc"; + + CharArray httpDirStr(httpDir.getData()); + CharArray fname(strlen(httpDirStr.buf)+strlen(name)+1); + sprintf(fname.buf, "%s%s", httpDirStr.buf, name); + int fd = open(fname.buf, O_RDONLY); + if (fd < 0) return 0; + rdr::InStream* is = new rdr::FdInStream(fd, -1, 0, true); + *contentType = guessContentType(name, *contentType); + if (strlen(name) > 4 && strcasecmp(&name[strlen(name)-4], ".vnc") == 0) { + is = new rdr::SubstitutingInStream(is, desktop, 20); + *contentType = "text/html"; + } else { + struct stat st; + if (fstat(fd, &st) == 0) { + *contentLength = st.st_size; + *lastModified = st.st_mtime; + } + } + return is; + } + + XserverDesktop* desktop; +}; + + +XserverDesktop::XserverDesktop(ScreenPtr pScreen_, + network::TcpListener* listener_, + network::TcpListener* httpListener_, + const char* name, void* fbptr) + : pScreen(pScreen_), deferredUpdateTimer(0), dummyTimer(0), + server(0), httpServer(0), + listener(listener_), httpListener(httpListener_), + cmap(0), deferredUpdateTimerSet(false), + grabbing(false), ignoreHooks_(false), directFbptr(fbptr != 0), + oldButtonMask(0), + queryConnectId(0) +{ + int i; + format.depth = pScreen->rootDepth; + for (i = 0; i < screenInfo.numPixmapFormats; i++) { + if (screenInfo.formats[i].depth == format.depth) { + format.bpp = screenInfo.formats[i].bitsPerPixel; + break; + } + } + if (i == screenInfo.numPixmapFormats) { + fprintf(stderr,"no pixmap format for root depth???\n"); + abort(); + } + format.bigEndian = (screenInfo.imageByteOrder == MSBFirst); + + VisualPtr vis; + for (i = 0; i < pScreen->numVisuals; i++) { + if (pScreen->visuals[i].vid == pScreen->rootVisual) { + vis = &pScreen->visuals[i]; + break; + } + } + if (i == pScreen->numVisuals) { + fprintf(stderr,"no visual rec for root visual???\n"); + abort(); + } + format.trueColour = (vis->c_class == TrueColor); + if (!format.trueColour && format.bpp != 8) + throw rfb::Exception("X server uses unsupported visual"); + format.redShift = ffs(vis->redMask) - 1; + format.greenShift = ffs(vis->greenMask) - 1; + format.blueShift = ffs(vis->blueMask) - 1; + format.redMax = vis->redMask >> format.redShift; + format.greenMax = vis->greenMask >> format.greenShift; + format.blueMax = vis->blueMask >> format.blueShift; + + width_ = pScreen->width; + height_ = pScreen->height; + if (fbptr) + data = (rdr::U8*)fbptr; + else + data = new rdr::U8[pScreen->width * pScreen->height * (format.bpp/8)]; + colourmap = this; + + serverReset(pScreen); + + server = new VNCServerST(name, this); + server->setPixelBuffer(this); + server->setQueryConnectionHandler(this); + + if (httpListener) + httpServer = new FileHTTPServer(this); +} + +XserverDesktop::~XserverDesktop() +{ + if (!directFbptr) + delete [] data; + TimerFree(deferredUpdateTimer); + TimerFree(dummyTimer); + delete httpServer; + delete server; +} + +void XserverDesktop::serverReset(ScreenPtr pScreen_) +{ + pScreen = pScreen_; + XID* ids = new XID[pScreen->maxInstalledCmaps]; + int nmaps = (*pScreen->ListInstalledColormaps)(pScreen, ids); + cmap = (ColormapPtr)LookupIDByType(ids[0], RT_COLORMAP); + delete [] ids; +} + +char* XserverDesktop::substitute(const char* varName) +{ + if (strcmp(varName, "$$") == 0) { + return rfb::strDup("$"); + } + if (strcmp(varName, "$PORT") == 0) { + char* str = new char[10]; + sprintf(str, "%d", listener ? listener->getMyPort() : 0); + return str; + } + if (strcmp(varName, "$WIDTH") == 0) { + char* str = new char[10]; + sprintf(str, "%d", width()); + return str; + } + if (strcmp(varName, "$HEIGHT") == 0) { + char* str = new char[10]; + sprintf(str, "%d", height()); + return str; + } + if (strcmp(varName, "$APPLETWIDTH") == 0) { + char* str = new char[10]; + sprintf(str, "%d", width()); + return str; + } + if (strcmp(varName, "$APPLETHEIGHT") == 0) { + char* str = new char[10]; + sprintf(str, "%d", height() + 32); + return str; + } + if (strcmp(varName, "$DESKTOP") == 0) { + return rfb::strDup(server->getName()); + } + if (strcmp(varName, "$DISPLAY") == 0) { + struct utsname uts; + uname(&uts); + char* str = new char[256]; + strncat(str, uts.nodename, 240); + strcat(str, ":"); + strncat(str, display, 10); + return str; + } + if (strcmp(varName, "$USER") == 0) { + struct passwd* user = getpwuid(getuid()); + return rfb::strDup(user ? user->pw_name : "?"); + } + return 0; +} + +rfb::VNCServerST::queryResult +XserverDesktop::queryConnection(network::Socket* sock, + const char* userName, + char** reason) { + if (queryConnectId) { + *reason = strDup("Another connection is currently being queried."); + return rfb::VNCServerST::REJECT; + } + queryConnectAddress.replaceBuf(sock->getPeerAddress()); + if (!userName) + userName = "(anonymous)"; + queryConnectUsername.replaceBuf(strDup(userName)); + queryConnectId = sock; + vncQueryConnect(this, sock); + return rfb::VNCServerST::PENDING; +} + + +void XserverDesktop::setColormap(ColormapPtr cmap_) +{ + if (cmap != cmap_) { + cmap = cmap_; + setColourMapEntries(0, 0); + } +} + +void XserverDesktop::setColourMapEntries(ColormapPtr pColormap, int ndef, + xColorItem* pdef) +{ + if (cmap != pColormap || ndef <= 0) return; + + int first = pdef[0].pixel; + int n = 1; + + for (int i = 1; i < ndef; i++) { + if (first + n == pdef[i].pixel) { + n++; + } else { + setColourMapEntries(first, n); + first = pdef[i].pixel; + n = 1; + } + } + setColourMapEntries(first, n); +} + +void XserverDesktop::setColourMapEntries(int firstColour, int nColours) +{ + try { + server->setColourMapEntries(firstColour, nColours); + } catch (rdr::Exception& e) { + vlog.error("XserverDesktop::setColourMapEntries: %s",e.str()); + } +} + +void XserverDesktop::bell() +{ + server->bell(); +} + +void XserverDesktop::serverCutText(const char* str, int len) +{ + try { + server->serverCutText(str, len); + } catch (rdr::Exception& e) { + vlog.error("XserverDesktop::serverCutText: %s",e.str()); + } +} + +void XserverDesktop::setCursor(CursorPtr cursor) +{ + try { + int w = cursor->bits->width; + int h = cursor->bits->height; + rdr::U8* cursorData = new rdr::U8[w * h * (getPF().bpp / 8)]; + + xColorItem fg, bg; + fg.red = cursor->foreRed; + fg.green = cursor->foreGreen; + fg.blue = cursor->foreBlue; + FakeAllocColor(cmap, &fg); + bg.red = cursor->backRed; + bg.green = cursor->backGreen; + bg.blue = cursor->backBlue; + FakeAllocColor(cmap, &bg); + FakeFreeColor(cmap, fg.pixel); + FakeFreeColor(cmap, bg.pixel); + + int xMaskBytesPerRow = BitmapBytePad(w); + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + int byte = y * xMaskBytesPerRow + x / 8; +#if (BITMAP_BIT_ORDER == MSBFirst) + int bit = 7 - x % 8; +#else + int bit = x % 8; +#endif + switch (getPF().bpp) { + case 8: + ((rdr::U8*)cursorData)[y * w + x] + = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel; + break; + case 16: + ((rdr::U16*)cursorData)[y * w + x] + = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel; + break; + case 32: + ((rdr::U32*)cursorData)[y * w + x] + = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel; + break; + } + } + } + + int rfbMaskBytesPerRow = (w + 7) / 8; + + rdr::U8* cursorMask = new rdr::U8[rfbMaskBytesPerRow * h]; + + for (int j = 0; j < h; j++) { + for (int i = 0; i < rfbMaskBytesPerRow; i++) +#if (BITMAP_BIT_ORDER == MSBFirst) + cursorMask[j * rfbMaskBytesPerRow + i] + = cursor->bits->mask[j * xMaskBytesPerRow + i]; +#else + cursorMask[j * rfbMaskBytesPerRow + i] + = reverseBits[cursor->bits->mask[j * xMaskBytesPerRow + i]]; +#endif + } + + server->setCursor(cursor->bits->width, cursor->bits->height, + Point(cursor->bits->xhot, cursor->bits->yhot), + cursorData, cursorMask); + server->tryUpdate(); + delete [] cursorData; + delete [] cursorMask; + } catch (rdr::Exception& e) { + vlog.error("XserverDesktop::setCursor: %s",e.str()); + } +} + +static void printRegion(RegionPtr reg) +{ + int nrects = REGION_NUM_RECTS(reg); + + fprintf(stderr,"Region num rects %2d extents %3d,%3d %3dx%3d\n",nrects, + (REGION_EXTENTS(pScreen,reg))->x1, + (REGION_EXTENTS(pScreen,reg))->y1, + (REGION_EXTENTS(pScreen,reg))->x2-(REGION_EXTENTS(pScreen,reg))->x1, + (REGION_EXTENTS(pScreen,reg))->y2-(REGION_EXTENTS(pScreen,reg))->y1); + + for (int i = 0; i < nrects; i++) { + fprintf(stderr," rect %3d,%3d %3dx%3d\n", + REGION_RECTS(reg)[i].x1, + REGION_RECTS(reg)[i].y1, + REGION_RECTS(reg)[i].x2-REGION_RECTS(reg)[i].x1, + REGION_RECTS(reg)[i].y2-REGION_RECTS(reg)[i].y1); + } +} + +CARD32 XserverDesktop::deferredUpdateTimerCallback(OsTimerPtr timer, + CARD32 now, pointer arg) +{ + XserverDesktop* desktop = (XserverDesktop*)arg; + desktop->deferredUpdateTimerSet = false; + try { + desktop->server->tryUpdate(); + } catch (rdr::Exception& e) { + vlog.error("XserverDesktop::deferredUpdateTimerCallback: %s",e.str()); + } + return 0; +} + +void XserverDesktop::deferUpdate() +{ + if (deferUpdateTime != 0) { + if (!deferredUpdateTimerSet || alwaysSetDeferUpdateTimer) { + deferredUpdateTimerSet = true; + deferredUpdateTimer = TimerSet(deferredUpdateTimer, 0, + deferUpdateTime, + deferredUpdateTimerCallback, this); + } + } else { + server->tryUpdate(); + } +} + +void XserverDesktop::add_changed(RegionPtr reg) +{ + if (ignoreHooks_) return; + if (grabbing) return; + try { + rfb::Region rfbReg; + rfbReg.setExtentsAndOrderedRects((ShortRect*)REGION_EXTENTS(pScreen, reg), + REGION_NUM_RECTS(reg), + (ShortRect*)REGION_RECTS(reg)); + server->add_changed(rfbReg); + deferUpdate(); + } catch (rdr::Exception& e) { + vlog.error("XserverDesktop::add_changed: %s",e.str()); + } +} + +void XserverDesktop::add_copied(RegionPtr dst, int dx, int dy) +{ + if (ignoreHooks_) return; + if (grabbing) return; + try { + rfb::Region rfbReg; + rfbReg.setExtentsAndOrderedRects((ShortRect*)REGION_EXTENTS(pScreen, dst), + REGION_NUM_RECTS(dst), + (ShortRect*)REGION_RECTS(dst)); + server->add_copied(rfbReg, rfb::Point(dx, dy)); + deferUpdate(); + } catch (rdr::Exception& e) { + vlog.error("XserverDesktop::add_copied: %s",e.str()); + } +} + +void XserverDesktop::positionCursor() +{ + if (!cursorPos.equals(oldCursorPos)) { + oldCursorPos = cursorPos; + (*pScreen->SetCursorPosition) (pScreen, cursorPos.x, cursorPos.y, FALSE); + server->setCursorPos(cursorPos); + server->tryUpdate(); + } +} + +void XserverDesktop::blockHandler(fd_set* fds) +{ + try { + ScreenPtr screenWithCursor = GetCurrentRootWindow()->drawable.pScreen; + if (screenWithCursor == pScreen) { + int x, y; + GetSpritePosition(&x, &y); + if (x != cursorPos.x || y != cursorPos.y) { + cursorPos = oldCursorPos = Point(x, y); + server->setCursorPos(cursorPos); + server->tryUpdate(); + } + } + + if (listener) + FD_SET(listener->getFd(), fds); + if (httpListener) + FD_SET(httpListener->getFd(), fds); + + std::list sockets; + server->getSockets(&sockets); + std::list::iterator i; + for (i = sockets.begin(); i != sockets.end(); i++) { + int fd = (*i)->getFd(); + if ((*i)->isShutdown()) { + vlog.debug("client gone, sock %d",fd); + server->removeSocket(*i); + vncClientGone(fd); + delete (*i); + } else { + FD_SET(fd, fds); + } + } + if (httpServer) { + httpServer->getSockets(&sockets); + for (i = sockets.begin(); i != sockets.end(); i++) { + int fd = (*i)->getFd(); + if ((*i)->isShutdown()) { + vlog.debug("http client gone, sock %d",fd); + httpServer->removeSocket(*i); + delete (*i); + } else { + FD_SET(fd, fds); + } + } + } + } catch (rdr::Exception& e) { + vlog.error("XserverDesktop::blockHandler: %s",e.str()); + } +} + +static CARD32 dummyTimerCallback(OsTimerPtr timer, CARD32 now, pointer arg) { + return 0; +} + +void XserverDesktop::wakeupHandler(fd_set* fds, int nfds) +{ + try { + if (nfds >= 1) { + + if (listener) { + if (FD_ISSET(listener->getFd(), fds)) { + FD_CLR(listener->getFd(), fds); + Socket* sock = listener->accept(); + server->addSocket(sock); + vlog.debug("new client, sock %d",sock->getFd()); + } + } + + if (httpListener) { + if (FD_ISSET(httpListener->getFd(), fds)) { + FD_CLR(httpListener->getFd(), fds); + Socket* sock = httpListener->accept(); + httpServer->addSocket(sock); + vlog.debug("new http client, sock %d",sock->getFd()); + } + } + + std::list sockets; + server->getSockets(&sockets); + std::list::iterator i; + for (i = sockets.begin(); i != sockets.end(); i++) { + int fd = (*i)->getFd(); + if (FD_ISSET(fd, fds)) { + FD_CLR(fd, fds); + server->processSocketEvent(*i); + } + } + + if (httpServer) { + httpServer->getSockets(&sockets); + for (i = sockets.begin(); i != sockets.end(); i++) { + int fd = (*i)->getFd(); + if (FD_ISSET(fd, fds)) { + FD_CLR(fd, fds); + httpServer->processSocketEvent(*i); + } + } + } + + positionCursor(); + } + + int timeout = server->checkTimeouts(); + if (timeout > 0) { + // set a dummy timer just so we are guaranteed be called again next time. + dummyTimer = TimerSet(dummyTimer, 0, timeout, + dummyTimerCallback, 0); + } + + } catch (rdr::Exception& e) { + vlog.error("XserverDesktop::wakeupHandler: %s",e.str()); + } +} + +void XserverDesktop::addClient(Socket* sock, bool reverse) +{ + vlog.debug("new client, sock %d reverse %d",sock->getFd(),reverse); + server->addSocket(sock, reverse); +} + +void XserverDesktop::disconnectClients() +{ + vlog.debug("disconnecting all clients"); + return server->closeClients("Disconnection from server end"); +} + + +int XserverDesktop::getQueryTimeout(void* opaqueId, + const char** address, + const char** username) +{ + if (opaqueId && queryConnectId == opaqueId) { + vlog.info("address=%s, username=%s, timeout=%d", + queryConnectAddress.buf, queryConnectUsername.buf, + (int)queryConnectTimeout); + if (address) *address = queryConnectAddress.buf; + if (username) *username = queryConnectUsername.buf; + return queryConnectTimeout; + } + return 0; +} + +void XserverDesktop::approveConnection(void* opaqueId, bool accept, + const char* rejectMsg) +{ + if (queryConnectId == opaqueId) { + server->approveConnection((network::Socket*)opaqueId, accept, rejectMsg); + queryConnectId = 0; + } +} + +/////////////////////////////////////////////////////////////////////////// +// +// SDesktop callbacks + + +void XserverDesktop::pointerEvent(const Point& pos, int buttonMask) +{ + xEvent ev; + DevicePtr dev = LookupPointerDevice(); + + // SetCursorPosition seems to be very expensive (at least on XFree86 3.3.6 + // for S3), so we delay calling it until positionCursor() is called at the + // end of processing a load of RFB. + //(*pScreen->SetCursorPosition) (pScreen, pos.x, pos.y, FALSE); + + NewCurrentScreen(pScreen, pos.x, pos.y); + + ev.u.u.type = MotionNotify; + ev.u.u.detail = 0; + ev.u.keyButtonPointer.rootX = pos.x; + ev.u.keyButtonPointer.rootY = pos.y; + ev.u.keyButtonPointer.time = GetTimeInMillis(); + + if (!pos.equals(cursorPos)) + (*dev->processInputProc)(&ev, (DeviceIntPtr)dev, 1); + + for (int i = 0; i < 5; i++) { + if ((buttonMask ^ oldButtonMask) & (1<processInputProc)(&ev, (DeviceIntPtr)dev, 1); + } + } + + cursorPos = pos; + oldButtonMask = buttonMask; +} + +void XserverDesktop::clientCutText(const char* str, int len) +{ + vncClientCutText(str, len); +} + +void XserverDesktop::grabRegion(const rfb::Region& region) +{ + if (directFbptr) return; + if (!pScreen->GetImage) { + vlog.error("VNC error: pScreen->GetImage == 0"); + return; + } + + grabbing = true; + + int bytesPerPixel = format.bpp/8; + int bytesPerRow = pScreen->width * bytesPerPixel; + + std::vector rects; + std::vector::iterator i; + region.get_rects(&rects); + for (i = rects.begin(); i != rects.end(); i++) { + for (int y = i->tl.y; y < i->br.y; y++) { + (*pScreen->GetImage) ((DrawablePtr)WindowTable[pScreen->myNum], + i->tl.x, y, i->width(), 1, + ZPixmap, (unsigned long)~0L, + ((char*)data + + y * bytesPerRow + i->tl.x * bytesPerPixel)); + } + } + grabbing = false; +} + +void XserverDesktop::lookup(int index, int* r, int* g, int* b) +{ + if ((cmap->c_class | DynamicClass) == DirectColor) { + VisualPtr v = cmap->pVisual; + *r = cmap->red [(index & v->redMask ) >> v->offsetRed ].co.local.red; + *g = cmap->green[(index & v->greenMask) >> v->offsetGreen].co.local.green; + *b = cmap->blue [(index & v->blueMask ) >> v->offsetBlue ].co.local.blue; + } else { + EntryPtr pent; + pent = (EntryPtr)&cmap->red[index]; + if (pent->fShared) { + *r = pent->co.shco.red->color; + *g = pent->co.shco.green->color; + *b = pent->co.shco.blue->color; + } else { + *r = pent->co.local.red; + *g = pent->co.local.green; + *b = pent->co.local.blue; + } + } +} + +// +// Keyboard handling +// + +#define IS_PRESSED(keyc, keycode) \ + ((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7))) + +// ModifierState is a class which helps simplify generating a "fake" press +// or release of shift, ctrl, alt, etc. An instance of the class is created +// for every modifier which may need to be pressed or released. Then either +// press() or release() may be called to make sure that the corresponding keys +// are in the right state. The destructor of the class automatically reverts +// to the previous state. Each modifier may have multiple keys associated with +// it, so in the case of a fake release, this may involve releasing more than +// one key. + +class ModifierState { +public: + ModifierState(DeviceIntPtr dev_, int modIndex_) + : dev(dev_), modIndex(modIndex_), nKeys(0), keys(0), pressed(false) + { + } + ~ModifierState() { + for (int i = 0; i < nKeys; i++) + generateXKeyEvent(keys[i], !pressed); + delete [] keys; + } + void press() { + KeyClassPtr keyc = dev->key; + if (!(keyc->state & (1<modifierKeyMap[modIndex * keyc->maxKeysPerModifier], + true); + pressed = true; + } + } + void release() { + KeyClassPtr keyc = dev->key; + if (keyc->state & (1<maxKeysPerModifier; k++) { + int keycode + = keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier + k]; + if (keycode && IS_PRESSED(keyc, keycode)) + tempKeyEvent(keycode, false); + } + } + } +private: + void tempKeyEvent(int keycode, bool down) { + if (keycode) { + if (!keys) keys = new int[dev->key->maxKeysPerModifier]; + keys[nKeys++] = keycode; + generateXKeyEvent(keycode, down); + } + } + void generateXKeyEvent(int keycode, bool down) { + xEvent ev; + ev.u.u.type = down ? KeyPress : KeyRelease; + ev.u.u.detail = keycode; + ev.u.keyButtonPointer.time = GetTimeInMillis(); + (*dev->c_public.processInputProc)(&ev, dev, 1); + vlog.debug("fake keycode %d %s", keycode, down ? "down" : "up"); + } + DeviceIntPtr dev; + int modIndex; + int nKeys; + int* keys; + bool pressed; +}; + + +// altKeysym is a table of alternative keysyms which have the same meaning. + +struct altKeysym_t { + KeySym a, b; +}; + +altKeysym_t altKeysym[] = { + { XK_Shift_L, XK_Shift_R }, + { XK_Control_L, XK_Control_R }, + { XK_Meta_L, XK_Meta_R }, + { XK_Alt_L, XK_Alt_R }, + { XK_Super_L, XK_Super_R }, + { XK_Hyper_L, XK_Hyper_R }, + { XK_KP_Space, XK_space }, + { XK_KP_Tab, XK_Tab }, + { XK_KP_Enter, XK_Return }, + { XK_KP_F1, XK_F1 }, + { XK_KP_F2, XK_F2 }, + { XK_KP_F3, XK_F3 }, + { XK_KP_F4, XK_F4 }, + { XK_KP_Home, XK_Home }, + { XK_KP_Left, XK_Left }, + { XK_KP_Up, XK_Up }, + { XK_KP_Right, XK_Right }, + { XK_KP_Down, XK_Down }, + { XK_KP_Page_Up, XK_Page_Up }, + { XK_KP_Page_Down, XK_Page_Down }, + { XK_KP_End, XK_End }, + { XK_KP_Begin, XK_Begin }, + { XK_KP_Insert, XK_Insert }, + { XK_KP_Delete, XK_Delete }, + { XK_KP_Equal, XK_equal }, + { XK_KP_Multiply, XK_asterisk }, + { XK_KP_Add, XK_plus }, + { XK_KP_Separator, XK_comma }, + { XK_KP_Subtract, XK_minus }, + { XK_KP_Decimal, XK_period }, + { XK_KP_Divide, XK_slash }, + { XK_KP_0, XK_0 }, + { XK_KP_1, XK_1 }, + { XK_KP_2, XK_2 }, + { XK_KP_3, XK_3 }, + { XK_KP_4, XK_4 }, + { XK_KP_5, XK_5 }, + { XK_KP_6, XK_6 }, + { XK_KP_7, XK_7 }, + { XK_KP_8, XK_8 }, + { XK_KP_9, XK_9 }, +}; + +// keyEvent() - work out the best keycode corresponding to the keysym sent by +// the viewer. This is non-trivial because we can't assume much about the +// local keyboard layout. We must also find out which column of the keyboard +// mapping the keysym is in, and alter the shift state appropriately. Column 0 +// means both shift and "mode_switch" (AltGr) must be released, column 1 means +// shift must be pressed and mode_switch released, column 2 means shift must be +// released and mode_switch pressed, and column 3 means both shift and +// mode_switch must be pressed. + +void XserverDesktop::keyEvent(rdr::U32 keysym, bool down) +{ + if (keysym == XK_Caps_Lock) { + vlog.debug("Ignoring caps lock"); + return; + } + DeviceIntPtr dev = (DeviceIntPtr)LookupKeyboardDevice(); + KeyClassPtr keyc = dev->key; + KeySymsPtr keymap = &keyc->curKeySyms; + + // find which modifier Mode_switch is on. + int modeSwitchMapIndex = 0; + for (int i = 3; i < 8; i++) { + for (int k = 0; k < keyc->maxKeysPerModifier; k++) { + int keycode = keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k]; + for (int j = 0; j < keymap->mapWidth; j++) { + if (keycode != 0 && + keymap->map[(keycode - keymap->minKeyCode) + * keymap->mapWidth + j] == XK_Mode_switch) + { + modeSwitchMapIndex = i; + break; + } + } + } + } + + int col = 0; + if (keyc->state & (1<state & (1<state & (1<maxKeyCode; kc >= keymap->minKeyCode; kc--) { + if (!keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth]) { + keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth] = keysym; + col = 0; + SendMappingNotify(MappingKeyboard, kc, 1, serverClient); + vlog.info("Added unknown keysym 0x%x to keycode %d",keysym,kc); + break; + } + } + if (kc < keymap->minKeyCode) { + vlog.info("Keyboard mapping full - ignoring unknown keysym 0x%x",keysym); + return; + } + } + + // See if it's a modifier key. If so, then don't do any auto-repeat, because + // the X server will translate each press into a release followed by a press. + for (int i = 0; i < 8; i++) { + for (int k = 0; k < keyc->maxKeysPerModifier; k++) { + if (kc == keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k] && + IS_PRESSED(keyc,kc) && down) + return; + } + } + + ModifierState shift(dev, ShiftMapIndex); + ModifierState modeSwitch(dev, modeSwitchMapIndex); + if (down) { + if (col & 1) + shift.press(); + else + shift.release(); + if (modeSwitchMapIndex) { + if (col & 2) + modeSwitch.press(); + else + modeSwitch.release(); + } + } + vlog.debug("keycode %d %s", kc, down ? "down" : "up"); + xEvent ev; + ev.u.u.type = down ? KeyPress : KeyRelease; + ev.u.u.detail = kc; + ev.u.keyButtonPointer.time = GetTimeInMillis(); + (*dev->c_public.processInputProc)(&ev, dev, 1); +} + + +void XConvertCase(KeySym sym, KeySym *lower, KeySym *upper) +{ + *lower = sym; + *upper = sym; + switch(sym >> 8) { + case 0: /* Latin 1 */ + if ((sym >= XK_A) && (sym <= XK_Z)) + *lower += (XK_a - XK_A); + else if ((sym >= XK_a) && (sym <= XK_z)) + *upper -= (XK_a - XK_A); + else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) + *lower += (XK_agrave - XK_Agrave); + else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) + *upper -= (XK_agrave - XK_Agrave); + else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) + *lower += (XK_oslash - XK_Ooblique); + else if ((sym >= XK_oslash) && (sym <= XK_thorn)) + *upper -= (XK_oslash - XK_Ooblique); + break; + case 1: /* Latin 2 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym == XK_Aogonek) + *lower = XK_aogonek; + else if (sym >= XK_Lstroke && sym <= XK_Sacute) + *lower += (XK_lstroke - XK_Lstroke); + else if (sym >= XK_Scaron && sym <= XK_Zacute) + *lower += (XK_scaron - XK_Scaron); + else if (sym >= XK_Zcaron && sym <= XK_Zabovedot) + *lower += (XK_zcaron - XK_Zcaron); + else if (sym == XK_aogonek) + *upper = XK_Aogonek; + else if (sym >= XK_lstroke && sym <= XK_sacute) + *upper -= (XK_lstroke - XK_Lstroke); + else if (sym >= XK_scaron && sym <= XK_zacute) + *upper -= (XK_scaron - XK_Scaron); + else if (sym >= XK_zcaron && sym <= XK_zabovedot) + *upper -= (XK_zcaron - XK_Zcaron); + else if (sym >= XK_Racute && sym <= XK_Tcedilla) + *lower += (XK_racute - XK_Racute); + else if (sym >= XK_racute && sym <= XK_tcedilla) + *upper -= (XK_racute - XK_Racute); + break; + case 2: /* Latin 3 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Hstroke && sym <= XK_Hcircumflex) + *lower += (XK_hstroke - XK_Hstroke); + else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex) + *lower += (XK_gbreve - XK_Gbreve); + else if (sym >= XK_hstroke && sym <= XK_hcircumflex) + *upper -= (XK_hstroke - XK_Hstroke); + else if (sym >= XK_gbreve && sym <= XK_jcircumflex) + *upper -= (XK_gbreve - XK_Gbreve); + else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex) + *lower += (XK_cabovedot - XK_Cabovedot); + else if (sym >= XK_cabovedot && sym <= XK_scircumflex) + *upper -= (XK_cabovedot - XK_Cabovedot); + break; + case 3: /* Latin 4 */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Rcedilla && sym <= XK_Tslash) + *lower += (XK_rcedilla - XK_Rcedilla); + else if (sym >= XK_rcedilla && sym <= XK_tslash) + *upper -= (XK_rcedilla - XK_Rcedilla); + else if (sym == XK_ENG) + *lower = XK_eng; + else if (sym == XK_eng) + *upper = XK_ENG; + else if (sym >= XK_Amacron && sym <= XK_Umacron) + *lower += (XK_amacron - XK_Amacron); + else if (sym >= XK_amacron && sym <= XK_umacron) + *upper -= (XK_amacron - XK_Amacron); + break; + case 6: /* Cyrillic */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE) + *lower -= (XK_Serbian_DJE - XK_Serbian_dje); + else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze) + *upper += (XK_Serbian_DJE - XK_Serbian_dje); + else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN) + *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu); + else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign) + *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu); + break; + case 7: /* Greek */ + /* Assume the KeySym is a legal value (ignore discontinuities) */ + if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent) + *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); + else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent && + sym != XK_Greek_iotaaccentdieresis && + sym != XK_Greek_upsilonaccentdieresis) + *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); + else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA) + *lower += (XK_Greek_alpha - XK_Greek_ALPHA); + else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega && + sym != XK_Greek_finalsmallsigma) + *upper -= (XK_Greek_alpha - XK_Greek_ALPHA); + break; + } +} + +static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col) +{ + register int per = keymap->mapWidth; + register KeySym *syms; + KeySym lsym, usym; + + if ((col < 0) || ((col >= per) && (col > 3)) || + (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode)) + return NoSymbol; + + syms = &keymap->map[(keycode - keymap->minKeyCode) * per]; + if (col < 4) { + if (col > 1) { + while ((per > 2) && (syms[per - 1] == NoSymbol)) + per--; + if (per < 3) + col -= 2; + } + if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) { + XConvertCase(syms[col&~1], &lsym, &usym); + if (!(col & 1)) + return lsym; + // I'm commenting out this logic because it's incorrect even though it + // was copied from the Xlib sources. The X protocol book quite clearly + // states that where a group consists of element 1 being a non-alphabetic + // keysym and element 2 being NoSymbol that you treat the second element + // as being the same as the first. This also tallies with the behaviour + // produced by the installed Xlib on my linux box (I believe this is + // because it uses some XKB code rather than the original Xlib code - + // compare XKBBind.c with KeyBind.c in lib/X11). + // else if (usym == lsym) + // return NoSymbol; + else + return usym; + } + } + return syms[col]; +} + +// KeysymToKeycode() - find the keycode and column corresponding to the given +// keysym. The value of col passed in should be the column determined from the +// current shift state. If the keysym can be found in that column we prefer +// that to finding it in a different column (which would require fake events to +// alter the shift state). + +static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col) +{ + register int i, j; + + j = *col; + for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { + if (KeyCodetoKeySym(keymap, i, j) == ks) + return i; + } + + for (j = 0; j < keymap->mapWidth; j++) { + for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { + if (KeyCodetoKeySym(keymap, i, j) == ks) { + *col = j; + return i; + } + } + } + return 0; +} diff --git a/unix/xc/programs/Xserver/vnc/XserverDesktop.h b/unix/xc/programs/Xserver/vnc/XserverDesktop.h new file mode 100644 index 00000000..880acc21 --- /dev/null +++ b/unix/xc/programs/Xserver/vnc/XserverDesktop.h @@ -0,0 +1,130 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +// +// XserverDesktop.h +// + +#ifndef __XSERVERDESKTOP_H__ +#define __XSERVERDESKTOP_H__ + +#include +#include +#include +#include +#include +#include + +extern "C" { +#define class c_class; +#include +#include +#undef class +} + +namespace rfb { + class VNCServerST; +} + +namespace network { class TcpListener; class Socket; } + +class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer, + public rfb::ColourMap, public rdr::Substitutor, + public rfb::VNCServerST::QueryConnectionHandler { +public: + + XserverDesktop(ScreenPtr pScreen, network::TcpListener* listener, + network::TcpListener* httpListener_, + const char* name, void* fbptr); + virtual ~XserverDesktop(); + + // methods called from X server code + void serverReset(ScreenPtr pScreen); + void setColormap(ColormapPtr cmap); + void setColourMapEntries(ColormapPtr pColormap, int ndef, xColorItem* pdef); + void bell(); + void serverCutText(const char* str, int len); + void setCursor(CursorPtr cursor); + void add_changed(RegionPtr reg); + void add_copied(RegionPtr dst, int dx, int dy); + void positionCursor(); + void ignoreHooks(bool b) { ignoreHooks_ = b; } + void blockHandler(fd_set* fds); + void wakeupHandler(fd_set* fds, int nfds); + void addClient(network::Socket* sock, bool reverse); + void disconnectClients(); + + // QueryConnect methods called from X server code + // getQueryTimeout() + // Returns the timeout associated with a particular + // connection, identified by an opaque Id passed to the + // X code earlier. Also optionally gets the address and + // name associated with that connection. + // Returns zero if the Id is not recognised. + int getQueryTimeout(void* opaqueId, + const char** address=0, + const char** username=0); + + // approveConnection() + // Used by X server code to supply the result of a query. + void approveConnection(void* opaqueId, bool accept, + const char* rejectMsg=0); + + // rfb::SDesktop callbacks + virtual void pointerEvent(const rfb::Point& pos, int buttonMask); + virtual void keyEvent(rdr::U32 key, bool down); + virtual void clientCutText(const char* str, int len); + virtual rfb::Point getFbSize() { return rfb::Point(width(), height()); } + + // rfb::PixelBuffer callbacks + virtual void grabRegion(const rfb::Region& r); + + // rfb::ColourMap callbacks + virtual void lookup(int index, int* r, int* g, int* b); + + // rdr::Substitutor callback + virtual char* substitute(const char* varName); + + // rfb::VNCServerST::QueryConnectionHandler callback + virtual rfb::VNCServerST::queryResult queryConnection(network::Socket* sock, + const char* userName, + char** reason); + +private: + void setColourMapEntries(int firstColour, int nColours); + static CARD32 deferredUpdateTimerCallback(OsTimerPtr timer, CARD32 now, + pointer arg); + void deferUpdate(); + ScreenPtr pScreen; + OsTimerPtr deferredUpdateTimer, dummyTimer; + rfb::VNCServerST* server; + rfb::HTTPServer* httpServer; + network::TcpListener* listener; + network::TcpListener* httpListener; + ColormapPtr cmap; + bool deferredUpdateTimerSet; + bool grabbing; + bool ignoreHooks_; + bool directFbptr; + int oldButtonMask; + rfb::Point cursorPos, oldCursorPos; + + void* queryConnectId; + rfb::CharArray queryConnectAddress; + rfb::CharArray queryConnectUsername; +}; +#endif diff --git a/unix/xc/programs/Xserver/vnc/Xvnc/Imakefile b/unix/xc/programs/Xserver/vnc/Xvnc/Imakefile new file mode 100644 index 00000000..93885ae3 --- /dev/null +++ b/unix/xc/programs/Xserver/vnc/Xvnc/Imakefile @@ -0,0 +1,95 @@ + + VNCTOP = $(TOP)/.. + VNCLIBS = VncExtLibs + VNCINCLUDE = -I$(VNCTOP) -I$(VNCTOP)/vncconfig_unix + +#if defined(XFree86Version) && XFree86Version < 4000 + VNCDEFINES = -DNO_INIT_BACKING_STORE +#endif + +#define CplusplusSource + +#include + +#if HasShm +SHMDEF = -DHAS_SHM +#endif + +XCOMM add more architectures here as we discover them +#if defined(HPArchitecture) || \ + (defined(SparcArchitecture) && !defined(LynxOSArchitecture)) || \ + SystemV4 || \ + defined(OSF1Architecture) || \ + defined(i386BsdArchitecture) || \ + defined(LinuxArchitecture) || \ + defined(DarwinArchitecture) +MMAPDEF = -DHAS_MMAP +#endif + +#ifdef XVendorString +VENDORSTRING = XVendorString +#else +VENDORSTRING = "unknown" +#endif + +#ifdef XVendorRelease +VENDORRELEASE = XVendorRelease +#else +VENDORRELEASE = 0 +#endif + + VENDOR_STRING = -DVENDOR_STRING=\"$(VENDORSTRING)\" + VENDOR_RELEASE = -DVENDOR_RELEASE="$(VENDORRELEASE)" + +#ifdef OS2Architecture +SRCS1 = os2_stubs.c +OBJS1 = os2_stubs.o +#endif + +FBINCLUDE = -I../../fb + +SRCSA = xvnc.cc stubs.c $(SRCS1) miinitext.c $(SRCS2) + +OBJSA = xvnc.o stubs.o $(OBJS1) miinitext.o $(OBJS2) + +INCLUDES = -I. -I.. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \ + $(FBINCLUDE) -I../../mfb -I../../mi -I../../include -I../../os \ + -I$(EXTINCSRC) -I$(XINCLUDESRC) -I$(SERVERSRC)/render $(VNCINCLUDE) + +DEFINES = $(OS_DEFINES) $(SHMDEF) $(MMAPDEF) $(FB_DEFINES) \ + $(VENDOR_STRING) $(VENDOR_RELEASE) $(STD_DEFINES) ServerOSDefines \ + $(VNCDEFINES) -UXFree86LOADER + +#ifdef XFree86Version +/* + * Make sure XINPUT, XF86VidTune, etc arent defined for the miinitext.o + * used by Xvnc + */ +EXT_DEFINES = ExtensionDefines -UXF86VIDMODE -UXFreeXDGA -UXF86MISC +#endif + + +SRCS = $(SRCSA) $(SRCSB) $(SRCSC) +OBJS = $(OBJSA) $(OBJSB) $(OBJSC) + +NormalLibraryObjectRule() +NormalLibraryTarget(xvnc,$(OBJS) buildtime.o) + +#ifdef OS2Architecture +LinkSourceFile(os2_stubs.c,../xfree86/os-support/os2) +SpecialCObjectRule(os2_stubs,$(ICONFIGFILES),-DOS2NULLSELECT) +#endif + +#ifdef HasGcc +NO_OPERATOR_NAMES = -fno-operator-names +#endif +LinkSourceFile(stubs.c,../../Xi) +SpecialCplusplusObjectRule(xvnc,$(ICONFIGFILES) xvnc,$(EXT_DEFINES) $(NO_OPERATOR_NAMES)) + +LinkSourceFile(miinitext.c,$(SERVERSRC)/mi) +SpecialCObjectRule(miinitext,$(ICONFIGFILES),$(EXT_DEFINES) $(PAN_DEFINES) -DNO_MODULE_EXTS $(EXT_MODULE_DEFINES) -UXFree86LOADER) + +/* InstallManPage(Xvfb,$(MANDIR)) */ +DependTarget() + +buildtime.o: $(OBJS) ../LibraryTargetName(vnc) $(VNCLIBS) diff --git a/unix/xc/programs/Xserver/vnc/Xvnc/buildtime.c b/unix/xc/programs/Xserver/vnc/Xvnc/buildtime.c new file mode 100644 index 00000000..3f4c3690 --- /dev/null +++ b/unix/xc/programs/Xserver/vnc/Xvnc/buildtime.c @@ -0,0 +1,18 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +char buildtime[] = __DATE__ " " __TIME__; diff --git a/unix/xc/programs/Xserver/vnc/Xvnc/xvnc.cc b/unix/xc/programs/Xserver/vnc/Xvnc/xvnc.cc new file mode 100644 index 00000000..fcb73e65 --- /dev/null +++ b/unix/xc/programs/Xserver/vnc/Xvnc/xvnc.cc @@ -0,0 +1,1475 @@ +/* Copyright (c) 1993 X Consortium + Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + +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 CONNECTION 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 dealings in this Software without prior written authorization +from the X Consortium. + +*/ + +#include +#include +#include +#include +#include "vncExtInit.h" + +extern "C" { +#define class c_class +#define public c_public +#define xor c_xor +#define and c_and +#ifdef WIN32 +#include +#endif +#include +#include "X11/X.h" +#define NEED_EVENTS +#include "X11/Xproto.h" +#include "X11/Xos.h" +#include "scrnintstr.h" +#include "servermd.h" +#include "fb.h" +#include "mi.h" +#include "mibstore.h" +#include "colormapst.h" +#include "gcstruct.h" +#include "input.h" +#include "mipointer.h" +#define new New +#include "micmap.h" +#undef new +#include +#ifdef HAS_MMAP +#include +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif +#endif /* HAS_MMAP */ +#include +#include +#ifndef WIN32 +#include +#endif +#include +#ifdef HAS_SHM +#include +#include +#endif /* HAS_SHM */ +#include "dix.h" +#include "miline.h" +#include "inputstr.h" +#include "keysym.h" + extern int defaultColorVisualClass; + extern char buildtime[]; +#undef class +#undef public +#undef xor +#undef and +} + +#define XVNCVERSION "Free Edition 4.1.1" +#define XVNCCOPYRIGHT ("Copyright (C) 2002-2005 RealVNC Ltd.\n" \ + "See http://www.realvnc.com for information on VNC.\n") + + +extern char *display; +extern int monitorResolution; + +#define VFB_DEFAULT_WIDTH 1024 +#define VFB_DEFAULT_HEIGHT 768 +#define VFB_DEFAULT_DEPTH 16 +#define VFB_DEFAULT_WHITEPIXEL 0xffff +#define VFB_DEFAULT_BLACKPIXEL 0 +#define VFB_DEFAULT_LINEBIAS 0 +#define XWD_WINDOW_NAME_LEN 60 + +typedef struct +{ + int scrnum; + int width; + int paddedBytesWidth; + int paddedWidth; + int height; + int depth; + int bitsPerPixel; + int sizeInBytes; + int ncolors; + char *pfbMemory; + XWDColor *pXWDCmap; + XWDFileHeader *pXWDHeader; + Pixel blackPixel; + Pixel whitePixel; + unsigned int lineBias; + CloseScreenProcPtr closeScreen; + +#ifdef HAS_MMAP + int mmap_fd; + char mmap_file[MAXPATHLEN]; +#endif + +#ifdef HAS_SHM + int shmid; +#endif + + Bool pixelFormatDefined; + Bool rgbNotBgr; + int redBits, greenBits, blueBits; + +} vfbScreenInfo, *vfbScreenInfoPtr; + +static int vfbNumScreens; +static vfbScreenInfo vfbScreens[MAXSCREENS]; +static Bool vfbPixmapDepths[33]; +#ifdef HAS_MMAP +static char *pfbdir = NULL; +#endif +typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType; +static fbMemType fbmemtype = NORMAL_MEMORY_FB; +static char needswap = 0; +static int lastScreen = -1; +static Bool Render = TRUE; + +static bool displaySpecified = false; +static bool wellKnownSocketsCreated = false; +static char displayNumStr[16]; + +#define swapcopy16(_dst, _src) \ + if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \ + else _dst = _src; + +#define swapcopy32(_dst, _src) \ + if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \ + else _dst = _src; + + +static void +vfbInitializePixmapDepths(void) +{ + int i; + vfbPixmapDepths[1] = TRUE; /* always need bitmaps */ + for (i = 2; i <= 32; i++) + vfbPixmapDepths[i] = FALSE; +} + +static void +vfbInitializeDefaultScreens(void) +{ + int i; + + for (i = 0; i < MAXSCREENS; i++) + { + vfbScreens[i].scrnum = i; + vfbScreens[i].width = VFB_DEFAULT_WIDTH; + vfbScreens[i].height = VFB_DEFAULT_HEIGHT; + vfbScreens[i].depth = VFB_DEFAULT_DEPTH; + vfbScreens[i].blackPixel = VFB_DEFAULT_BLACKPIXEL; + vfbScreens[i].whitePixel = VFB_DEFAULT_WHITEPIXEL; + vfbScreens[i].lineBias = VFB_DEFAULT_LINEBIAS; + vfbScreens[i].pixelFormatDefined = FALSE; + vfbScreens[i].pfbMemory = NULL; + } + vfbNumScreens = 1; +} + +static int +vfbBitsPerPixel(int depth) +{ + if (depth == 1) return 1; + else if (depth <= 8) return 8; + else if (depth <= 16) return 16; + else return 32; +} + + +extern "C" { + + /* ddxInitGlobals - called by |InitGlobals| from os/util.c in XOrg */ + void ddxInitGlobals(void) + { + } + + void ddxGiveUp() + { + int i; + + /* clean up the framebuffers */ + + switch (fbmemtype) + { +#ifdef HAS_MMAP + case MMAPPED_FILE_FB: + for (i = 0; i < vfbNumScreens; i++) + { + if (-1 == unlink(vfbScreens[i].mmap_file)) + { + perror("unlink"); + ErrorF("unlink %s failed, errno %d", + vfbScreens[i].mmap_file, errno); + } + } + break; +#else /* HAS_MMAP */ + case MMAPPED_FILE_FB: + break; +#endif /* HAS_MMAP */ + +#ifdef HAS_SHM + case SHARED_MEMORY_FB: + for (i = 0; i < vfbNumScreens; i++) + { + if (-1 == shmdt((char *)vfbScreens[i].pXWDHeader)) + { + perror("shmdt"); + ErrorF("shmdt failed, errno %d", errno); + } + } + break; +#else /* HAS_SHM */ + case SHARED_MEMORY_FB: + break; +#endif /* HAS_SHM */ + + case NORMAL_MEMORY_FB: + for (i = 0; i < vfbNumScreens; i++) + { + Xfree(vfbScreens[i].pXWDHeader); + } + break; + } +} + +void +AbortDDX() +{ + ddxGiveUp(); +} + +#ifdef __DARWIN__ +void +DarwinHandleGUI(int argc, char *argv[]) +{ +} + +void GlxExtensionInit(); +void GlxWrapInitVisuals(void *procPtr); + +void +DarwinGlxExtensionInit() +{ + GlxExtensionInit(); +} + +void +DarwinGlxWrapInitVisuals( + void *procPtr) +{ + GlxWrapInitVisuals(procPtr); +} +#endif + +void +OsVendorInit() +{ +} + +void +OsVendorFatalError() +{ +} + +void ddxBeforeReset(void) +{ + return; +} + +void +ddxUseMsg() +{ + ErrorF("\nXvnc %s - built %s\n%s", XVNCVERSION, buildtime, XVNCCOPYRIGHT); + ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE, + VENDOR_STRING); + ErrorF("-screen scrn WxHxD set screen's width, height, depth\n"); + ErrorF("-pixdepths list-of-int support given pixmap depths\n"); +#ifdef RENDER + ErrorF("+/-render turn on/off RENDER extension support" + "(default on)\n"); +#endif + ErrorF("-linebias n adjust thin line pixelization\n"); + ErrorF("-blackpixel n pixel value for black\n"); + ErrorF("-whitepixel n pixel value for white\n"); + +#ifdef HAS_MMAP + ErrorF("-fbdir directory put framebuffers in mmap'ed files in directory\n"); +#endif + +#ifdef HAS_SHM + ErrorF("-shmem put framebuffers in shared memory\n"); +#endif + + ErrorF("-geometry WxH set screen 0's width, height\n"); + ErrorF("-depth D set screen 0's depth\n"); + ErrorF("-pixelformat fmt set pixel format (rgbNNN or bgrNNN)\n"); + ErrorF("-inetd has been launched from inetd\n"); + ErrorF("\nVNC parameters:\n"); + + fprintf(stderr,"\n" + "Parameters can be turned on with - or off with -=0\n" + "Parameters which take a value can be specified as " + "- \n" + "Other valid forms are = -= " + "--=\n" + "Parameter names are case-insensitive. The parameters are:\n\n"); + rfb::Configuration::listParams(79, 14); + } +} + +/* ddxInitGlobals - called by |InitGlobals| from os/util.c */ +void ddxInitGlobals(void) +{ +} + +static +bool displayNumFree(int num) +{ + try { + network::TcpListener l(6000+num); + } catch (rdr::Exception& e) { + return false; + } + char file[256]; + sprintf(file, "/tmp/.X%d-lock", num); + if (access(file, F_OK) == 0) return false; + sprintf(file, "/tmp/.X11-unix/X%d", num); + if (access(file, F_OK) == 0) return false; + sprintf(file, "/usr/spool/sockets/X11/%d", num); + if (access(file, F_OK) == 0) return false; + return true; +} + +int +ddxProcessArgument(int argc, char *argv[], int i) +{ + static Bool firstTime = TRUE; + + if (firstTime) + { + vfbInitializeDefaultScreens(); + vfbInitializePixmapDepths(); + firstTime = FALSE; + rfb::initStdIOLoggers(); + rfb::LogWriter::setLogParams("*:stderr:30"); + } + + if (argv[i][0] == ':') + displaySpecified = true; + + if (strcmp (argv[i], "-screen") == 0) /* -screen n WxHxD */ + { + int screenNum; + if (i + 2 >= argc) UseMsg(); + screenNum = atoi(argv[i+1]); + if (screenNum < 0 || screenNum >= MAXSCREENS) + { + ErrorF("Invalid screen number %d\n", screenNum); + UseMsg(); + } + if (3 != sscanf(argv[i+2], "%dx%dx%d", + &vfbScreens[screenNum].width, + &vfbScreens[screenNum].height, + &vfbScreens[screenNum].depth)) + { + ErrorF("Invalid screen configuration %s\n", argv[i+2]); + UseMsg(); + } + + if (screenNum >= vfbNumScreens) + vfbNumScreens = screenNum + 1; + lastScreen = screenNum; + return 3; + } + + if (strcmp (argv[i], "-pixdepths") == 0) /* -pixdepths list-of-depth */ + { + int depth, ret = 1; + + if (++i >= argc) UseMsg(); + while ((i < argc) && (depth = atoi(argv[i++])) != 0) + { + if (depth < 0 || depth > 32) + { + ErrorF("Invalid pixmap depth %d\n", depth); + UseMsg(); + } + vfbPixmapDepths[depth] = TRUE; + ret++; + } + return ret; + } + + if (strcmp (argv[i], "+render") == 0) /* +render */ + { + Render = TRUE; + return 1; + } + + if (strcmp (argv[i], "-render") == 0) /* -render */ + { + Render = FALSE; + return 1; + } + + if (strcmp (argv[i], "-blackpixel") == 0) /* -blackpixel n */ + { + Pixel pix; + if (++i >= argc) UseMsg(); + pix = atoi(argv[i]); + if (-1 == lastScreen) + { + int i; + for (i = 0; i < MAXSCREENS; i++) + { + vfbScreens[i].blackPixel = pix; + } + } + else + { + vfbScreens[lastScreen].blackPixel = pix; + } + return 2; + } + + if (strcmp (argv[i], "-whitepixel") == 0) /* -whitepixel n */ + { + Pixel pix; + if (++i >= argc) UseMsg(); + pix = atoi(argv[i]); + if (-1 == lastScreen) + { + int i; + for (i = 0; i < MAXSCREENS; i++) + { + vfbScreens[i].whitePixel = pix; + } + } + else + { + vfbScreens[lastScreen].whitePixel = pix; + } + return 2; + } + + if (strcmp (argv[i], "-linebias") == 0) /* -linebias n */ + { + unsigned int linebias; + if (++i >= argc) UseMsg(); + linebias = atoi(argv[i]); + if (-1 == lastScreen) + { + int i; + for (i = 0; i < MAXSCREENS; i++) + { + vfbScreens[i].lineBias = linebias; + } + } + else + { + vfbScreens[lastScreen].lineBias = linebias; + } + return 2; + } + +#ifdef HAS_MMAP + if (strcmp (argv[i], "-fbdir") == 0) /* -fbdir directory */ + { + if (++i >= argc) UseMsg(); + pfbdir = argv[i]; + fbmemtype = MMAPPED_FILE_FB; + return 2; + } +#endif /* HAS_MMAP */ + +#ifdef HAS_SHM + if (strcmp (argv[i], "-shmem") == 0) /* -shmem */ + { + fbmemtype = SHARED_MEMORY_FB; + return 1; + } +#endif + + if (strcmp(argv[i], "-geometry") == 0) + { + if (++i >= argc) UseMsg(); + if (sscanf(argv[i],"%dx%d",&vfbScreens[0].width, + &vfbScreens[0].height) != 2) { + ErrorF("Invalid geometry %s\n", argv[i]); + UseMsg(); + } + return 2; + } + + if (strcmp(argv[i], "-depth") == 0) + { + if (++i >= argc) UseMsg(); + vfbScreens[0].depth = atoi(argv[i]); + return 2; + } + + if (strcmp(argv[i], "-pixelformat") == 0) + { + char rgbbgr[4]; + int bits1, bits2, bits3; + if (++i >= argc) UseMsg(); + if (sscanf(argv[i], "%3s%1d%1d%1d", rgbbgr,&bits1,&bits2,&bits3) < 4) { + ErrorF("Invalid pixel format %s\n", argv[i]); + UseMsg(); + } + +#define SET_PIXEL_FORMAT(vfbScreen) \ + (vfbScreen).pixelFormatDefined = TRUE; \ + (vfbScreen).depth = bits1 + bits2 + bits3; \ + (vfbScreen).greenBits = bits2; \ + if (strcasecmp(rgbbgr, "bgr") == 0) { \ + (vfbScreen).rgbNotBgr = FALSE; \ + (vfbScreen).redBits = bits3; \ + (vfbScreen).blueBits = bits1; \ + } else if (strcasecmp(rgbbgr, "rgb") == 0) { \ + (vfbScreen).rgbNotBgr = TRUE; \ + (vfbScreen).redBits = bits1; \ + (vfbScreen).blueBits = bits3; \ + } else { \ + ErrorF("Invalid pixel format %s\n", argv[i]); \ + UseMsg(); \ + } + + if (-1 == lastScreen) + { + int i; + for (i = 0; i < MAXSCREENS; i++) + { + SET_PIXEL_FORMAT(vfbScreens[i]); + } + } + else + { + SET_PIXEL_FORMAT(vfbScreens[lastScreen]); + } + + return 2; + } + + if (strcmp(argv[i], "-inetd") == 0) + { + dup2(0,3); + vncInetdSock = 3; + close(2); + + if (!displaySpecified) { + int port = network::TcpSocket::getSockPort(vncInetdSock); + int displayNum = port - 5900; + if (displayNum < 0 || displayNum > 99 || !displayNumFree(displayNum)) { + for (displayNum = 1; displayNum < 100; displayNum++) + if (displayNumFree(displayNum)) break; + + if (displayNum == 100) + FatalError("Xvnc error: no free display number for -inetd"); + } + + display = displayNumStr; + sprintf(displayNumStr, "%d", displayNum); + } + + return 1; + } + + if (rfb::Configuration::setParam(argv[i])) + return 1; + + if (argv[i][0] == '-' && i+1 < argc) { + if (rfb::Configuration::setParam(&argv[i][1], argv[i+1])) + return 2; + } + + return 0; +} + +#ifdef DDXTIME /* from ServerOSDefines */ +CARD32 +GetTimeInMillis() +{ + struct timeval tp; + + X_GETTIMEOFDAY(&tp); + return(tp.tv_sec * 1000) + (tp.tv_usec / 1000); +} +#endif + +static ColormapPtr InstalledMaps[MAXSCREENS]; + +static int +vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps) +{ + /* By the time we are processing requests, we can guarantee that there + * is always a colormap installed */ + *pmaps = InstalledMaps[pScreen->myNum]->mid; + return (1); +} + + +static void +vfbInstallColormap(ColormapPtr pmap) +{ + int index = pmap->pScreen->myNum; + ColormapPtr oldpmap = InstalledMaps[index]; + + if (pmap != oldpmap) + { + int entries; + XWDFileHeader *pXWDHeader; + XWDColor *pXWDCmap; + VisualPtr pVisual; + Pixel * ppix; + xrgb * prgb; + xColorItem *defs; + int i; + + if(oldpmap != (ColormapPtr)None) + WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid); + /* Install pmap */ + InstalledMaps[index] = pmap; + WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); + + entries = pmap->pVisual->ColormapEntries; + pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader; + pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap; + pVisual = pmap->pVisual; + + swapcopy32(pXWDHeader->visual_class, pVisual->c_class); + swapcopy32(pXWDHeader->red_mask, pVisual->redMask); + swapcopy32(pXWDHeader->green_mask, pVisual->greenMask); + swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask); + swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue); + swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries); + + ppix = (Pixel *)ALLOCATE_LOCAL(entries * sizeof(Pixel)); + prgb = (xrgb *)ALLOCATE_LOCAL(entries * sizeof(xrgb)); + defs = (xColorItem *)ALLOCATE_LOCAL(entries * sizeof(xColorItem)); + + for (i = 0; i < entries; i++) ppix[i] = i; + /* XXX truecolor */ + QueryColors(pmap, entries, ppix, prgb); + + for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */ + defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */ + defs[i].red = prgb[i].red; + defs[i].green = prgb[i].green; + defs[i].blue = prgb[i].blue; + defs[i].flags = DoRed|DoGreen|DoBlue; + } + (*pmap->pScreen->StoreColors)(pmap, entries, defs); + + DEALLOCATE_LOCAL(ppix); + DEALLOCATE_LOCAL(prgb); + DEALLOCATE_LOCAL(defs); + } +} + +static void +vfbUninstallColormap(ColormapPtr pmap) +{ + ColormapPtr curpmap = InstalledMaps[pmap->pScreen->myNum]; + + if(pmap == curpmap) + { + if (pmap->mid != pmap->pScreen->defColormap) + { + curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap, + RT_COLORMAP); + (*pmap->pScreen->InstallColormap)(curpmap); + } + } +} + +static void +vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs) +{ + XWDColor *pXWDCmap; + int i; + + if (pmap != InstalledMaps[pmap->pScreen->myNum]) + { + return; + } + + pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap; + + if ((pmap->pVisual->c_class | DynamicClass) == DirectColor) + { + return; + } + + for (i = 0; i < ndef; i++) + { + if (pdefs[i].flags & DoRed) + { + swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red); + } + if (pdefs[i].flags & DoGreen) + { + swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green); + } + if (pdefs[i].flags & DoBlue) + { + swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue); + } + } +} + +static Bool +vfbSaveScreen(ScreenPtr pScreen, int on) +{ + return TRUE; +} + +#ifdef HAS_MMAP + +/* this flushes any changes to the screens out to the mmapped file */ +static void +vfbBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) +{ + int i; + + for (i = 0; i < vfbNumScreens; i++) + { +#ifdef MS_ASYNC + if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader, + (size_t)vfbScreens[i].sizeInBytes, MS_ASYNC)) +#else + /* silly NetBSD and who else? */ + if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader, + (size_t)vfbScreens[i].sizeInBytes)) +#endif + { + perror("msync"); + ErrorF("msync failed, errno %d", errno); + } + } +} + + +static void +vfbWakeupHandler(pointer blockData, int result, pointer pReadmask) +{ +} + + +static void +vfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb) +{ +#define DUMMY_BUFFER_SIZE 65536 + char dummyBuffer[DUMMY_BUFFER_SIZE]; + int currentFileSize, writeThisTime; + + sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, pvfb->scrnum); + if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666))) + { + perror("open"); + ErrorF("open %s failed, errno %d", pvfb->mmap_file, errno); + return; + } + + /* Extend the file to be the proper size */ + + bzero(dummyBuffer, DUMMY_BUFFER_SIZE); + for (currentFileSize = 0; + currentFileSize < pvfb->sizeInBytes; + currentFileSize += writeThisTime) + { + writeThisTime = min(DUMMY_BUFFER_SIZE, + pvfb->sizeInBytes - currentFileSize); + if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime)) + { + perror("write"); + ErrorF("write %s failed, errno %d", pvfb->mmap_file, errno); + return; + } + } + + /* try to mmap the file */ + + pvfb->pXWDHeader = (XWDFileHeader *)mmap((caddr_t)NULL, pvfb->sizeInBytes, + PROT_READ|PROT_WRITE, + MAP_FILE|MAP_SHARED, + pvfb->mmap_fd, 0); + if (-1 == (long)pvfb->pXWDHeader) + { + perror("mmap"); + ErrorF("mmap %s failed, errno %d", pvfb->mmap_file, errno); + pvfb->pXWDHeader = NULL; + return; + } + + if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler, + NULL)) + { + pvfb->pXWDHeader = NULL; + } +} +#endif /* HAS_MMAP */ + + +#ifdef HAS_SHM +static void +vfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb) +{ + /* create the shared memory segment */ + + pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT|0777); + if (pvfb->shmid < 0) + { + perror("shmget"); + ErrorF("shmget %d bytes failed, errno %d", pvfb->sizeInBytes, errno); + return; + } + + /* try to attach it */ + + pvfb->pXWDHeader = (XWDFileHeader *)shmat(pvfb->shmid, 0, 0); + if (-1 == (long)pvfb->pXWDHeader) + { + perror("shmat"); + ErrorF("shmat failed, errno %d", errno); + pvfb->pXWDHeader = NULL; + return; + } + + ErrorF("screen %d shmid %d\n", pvfb->scrnum, pvfb->shmid); +} +#endif /* HAS_SHM */ + + +static char * +vfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb) +{ + if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */ + + pvfb->sizeInBytes = pvfb->paddedBytesWidth * pvfb->height; + + /* Calculate how many entries in colormap. This is rather bogus, because + * the visuals haven't even been set up yet, but we need to know because we + * have to allocate space in the file for the colormap. The number 10 + * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c. + */ + + if (pvfb->depth <= 10) + { /* single index colormaps */ + pvfb->ncolors = 1 << pvfb->depth; + } + else + { /* decomposed colormaps */ + int nplanes_per_color_component = pvfb->depth / 3; + if (pvfb->depth % 3) nplanes_per_color_component++; + pvfb->ncolors = 1 << nplanes_per_color_component; + } + + /* add extra bytes for XWDFileHeader, window name, and colormap */ + + pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN + + pvfb->ncolors * SIZEOF(XWDColor); + + pvfb->pXWDHeader = NULL; + switch (fbmemtype) + { +#ifdef HAS_MMAP + case MMAPPED_FILE_FB: vfbAllocateMmappedFramebuffer(pvfb); break; +#else + case MMAPPED_FILE_FB: break; +#endif + +#ifdef HAS_SHM + case SHARED_MEMORY_FB: vfbAllocateSharedMemoryFramebuffer(pvfb); break; +#else + case SHARED_MEMORY_FB: break; +#endif + + case NORMAL_MEMORY_FB: + pvfb->pXWDHeader = (XWDFileHeader *)Xalloc(pvfb->sizeInBytes); + break; + } + + if (pvfb->pXWDHeader) + { + pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader + + SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN); + pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors); + + return pvfb->pfbMemory; + } + else + return NULL; +} + +static void +vfbWriteXWDFileHeader(ScreenPtr pScreen) +{ + vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum]; + XWDFileHeader *pXWDHeader = pvfb->pXWDHeader; + char hostname[XWD_WINDOW_NAME_LEN]; + unsigned long swaptest = 1; + int i; + + needswap = *(char *) &swaptest; + + pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader; + pXWDHeader->file_version = XWD_FILE_VERSION; + + pXWDHeader->pixmap_format = ZPixmap; + pXWDHeader->pixmap_depth = pvfb->depth; + pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height; + pXWDHeader->xoffset = 0; + pXWDHeader->byte_order = IMAGE_BYTE_ORDER; + pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER; +#ifndef INTERNAL_VS_EXTERNAL_PADDING + pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width; + pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT; + pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD; +#else + pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth; + pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO; + pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO; +#endif + pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel; + pXWDHeader->bytes_per_line = pvfb->paddedBytesWidth; + pXWDHeader->ncolors = pvfb->ncolors; + + /* visual related fields are written when colormap is installed */ + + pXWDHeader->window_x = pXWDHeader->window_y = 0; + pXWDHeader->window_bdrwidth = 0; + + /* write xwd "window" name: Xvfb hostname:server.screen */ + + if (-1 == gethostname(hostname, sizeof(hostname))) + hostname[0] = 0; + else + hostname[XWD_WINDOW_NAME_LEN-1] = 0; + sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display, + pScreen->myNum); + + /* write colormap pixel slot values */ + + for (i = 0; i < pvfb->ncolors; i++) + { + pvfb->pXWDCmap[i].pixel = i; + } + + /* byte swap to most significant byte first */ + + if (needswap) + { + SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4); + for (i = 0; i < pvfb->ncolors; i++) + { + register char n; + swapl(&pvfb->pXWDCmap[i].pixel, n); + } + } +} + + +static Bool +vfbCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y) +{ + return FALSE; +} + +static void +vfbCrossScreen (ScreenPtr pScreen, Bool entering) +{ +} + +static Bool vfbRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) { + return TRUE; +} + +static Bool vfbUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) { + return TRUE; +} + +static void vfbSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +{ +} + +static void vfbMoveCursor(ScreenPtr pScreen, int x, int y) +{ +} + +static miPointerSpriteFuncRec vfbPointerSpriteFuncs = { + vfbRealizeCursor, + vfbUnrealizeCursor, + vfbSetCursor, + vfbMoveCursor +}; + +static miPointerScreenFuncRec vfbPointerCursorFuncs = { + vfbCursorOffScreen, + vfbCrossScreen, + miPointerWarpCursor +}; + +static Bool +vfbCloseScreen(int index, ScreenPtr pScreen) +{ + vfbScreenInfoPtr pvfb = &vfbScreens[index]; + int i; + + pScreen->CloseScreen = pvfb->closeScreen; + + /* + * XXX probably lots of stuff to clean. For now, + * clear InstalledMaps[] so that server reset works correctly. + */ + for (i = 0; i < MAXSCREENS; i++) + InstalledMaps[i] = NULL; + + return pScreen->CloseScreen(index, pScreen); +} + +static Bool +vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) +{ + vfbScreenInfoPtr pvfb = &vfbScreens[index]; + int dpi = 100; + int ret; + char *pbits; + + if (monitorResolution) dpi = monitorResolution; + + pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth); + pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth); + pvfb->paddedWidth = pvfb->paddedBytesWidth * 8 / pvfb->bitsPerPixel; + pbits = vfbAllocateFramebufferMemory(pvfb); + if (!pbits) return FALSE; + vncFbptr[index] = pbits; + + defaultColorVisualClass + = (pvfb->bitsPerPixel > 8) ? TrueColor : PseudoColor; + + ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height, + dpi, dpi, pvfb->paddedWidth, pvfb->bitsPerPixel); + +#ifdef RENDER + if (ret && Render) + fbPictureInit (pScreen, 0, 0); +#endif + + if (!ret) return FALSE; + + /* miInitializeBackingStore(pScreen); */ + + /* + * Circumvent the backing store that was just initialised. This amounts + * to a truely bizarre way of initialising SaveDoomedAreas and friends. + */ + + pScreen->InstallColormap = vfbInstallColormap; + pScreen->UninstallColormap = vfbUninstallColormap; + pScreen->ListInstalledColormaps = vfbListInstalledColormaps; + + pScreen->SaveScreen = vfbSaveScreen; + pScreen->StoreColors = vfbStoreColors; + + miPointerInitialize(pScreen, &vfbPointerSpriteFuncs, &vfbPointerCursorFuncs, + FALSE); + + vfbWriteXWDFileHeader(pScreen); + + pScreen->blackPixel = pvfb->blackPixel; + pScreen->whitePixel = pvfb->whitePixel; + + if (!pvfb->pixelFormatDefined && pvfb->depth == 16) { + pvfb->pixelFormatDefined = TRUE; + pvfb->rgbNotBgr = TRUE; + pvfb->blueBits = pvfb->redBits = 5; + pvfb->greenBits = 6; + } + + if (pvfb->pixelFormatDefined) { + VisualPtr vis = pScreen->visuals; + for (int i = 0; i < pScreen->numVisuals; i++) { + if (pvfb->rgbNotBgr) { + vis->offsetBlue = 0; + vis->blueMask = (1 << pvfb->blueBits) - 1; + vis->offsetGreen = pvfb->blueBits; + vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen; + vis->offsetRed = vis->offsetGreen + pvfb->greenBits; + vis->redMask = ((1 << pvfb->redBits) - 1) << vis->offsetRed; + } else { + vis->offsetRed = 0; + vis->redMask = (1 << pvfb->redBits) - 1; + vis->offsetGreen = pvfb->redBits; + vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen; + vis->offsetBlue = vis->offsetGreen + pvfb->greenBits; + vis->blueMask = ((1 << pvfb->blueBits) - 1) << vis->offsetBlue; + } + vis++; + } + } + + ret = fbCreateDefColormap(pScreen); + + miSetZeroLineBias(pScreen, pvfb->lineBias); + + pvfb->closeScreen = pScreen->CloseScreen; + pScreen->CloseScreen = vfbCloseScreen; + +#ifndef NO_INIT_BACKING_STORE + miInitializeBackingStore(pScreen); + pScreen->backingStoreSupport = Always; +#endif + + return ret; + +} /* end vfbScreenInit */ + + +static void vfbClientStateChange(CallbackListPtr*, pointer, pointer) { + dispatchException &= ~DE_RESET; +} + +void +InitOutput(ScreenInfo *screenInfo, int argc, char **argv) +{ + ErrorF("\nXvnc %s - built %s\n%s", XVNCVERSION, buildtime, XVNCCOPYRIGHT); + ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE, + VENDOR_STRING); + int i; + int NumFormats = 0; + + /* initialize pixmap formats */ + + /* must have a pixmap depth to match every screen depth */ + for (i = 0; i < vfbNumScreens; i++) + { + vfbPixmapDepths[vfbScreens[i].depth] = TRUE; + } + + /* RENDER needs a good set of pixmaps. */ + if (Render) { + vfbPixmapDepths[1] = TRUE; + vfbPixmapDepths[4] = TRUE; + vfbPixmapDepths[8] = TRUE; +/* vfbPixmapDepths[15] = TRUE; */ + vfbPixmapDepths[16] = TRUE; + vfbPixmapDepths[24] = TRUE; + vfbPixmapDepths[32] = TRUE; + } + + for (i = 1; i <= 32; i++) + { + if (vfbPixmapDepths[i]) + { + if (NumFormats >= MAXFORMATS) + FatalError ("MAXFORMATS is too small for this server\n"); + screenInfo->formats[NumFormats].depth = i; + screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i); + screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD; + NumFormats++; + } + } + + screenInfo->imageByteOrder = IMAGE_BYTE_ORDER; + screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; + screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; + screenInfo->numPixmapFormats = NumFormats; + + /* initialize screens */ + + for (i = 0; i < vfbNumScreens; i++) + { + if (-1 == AddScreen(vfbScreenInit, argc, argv)) + { + FatalError("Couldn't add screen %d", i); + } + } + + if (!AddCallback(&ClientStateCallback, vfbClientStateChange, 0)) { + FatalError("AddCallback failed\n"); + } +} /* end InitOutput */ + +#ifdef DPMSExtension +extern "C" { +#if NeedFunctionPrototypes + void DPMSSet(CARD16 level) +#else + void DPMSSet(level) + CARD16 level; +#endif + { + return; + } + + Bool DPMSSupported() + { + return FALSE; + } +} +#endif + +/* this is just to get the server to link on AIX */ +#ifdef AIXV3 +int SelectWaitTime = 10000; /* usec */ +#endif + +Bool LegalModifier(unsigned int key, DevicePtr pDev) +{ + return TRUE; +} + +void ProcessInputEvents() +{ + mieqProcessInputEvents(); + miPointerUpdate(); +} + +/* Fairly standard US PC Keyboard */ + +#define VFB_MIN_KEY 8 +#define VFB_MAX_KEY 255 +#define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1) +#define KEYSYMS_PER_KEY 2 +KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = { + NoSymbol, NoSymbol, + XK_Escape, NoSymbol, + XK_1, XK_exclam, + XK_2, XK_at, + XK_3, XK_numbersign, + XK_4, XK_dollar, + XK_5, XK_percent, + XK_6, XK_asciicircum, + XK_7, XK_ampersand, + XK_8, XK_asterisk, + XK_9, XK_parenleft, + XK_0, XK_parenright, + XK_minus, XK_underscore, + XK_equal, XK_plus, + XK_BackSpace, NoSymbol, + XK_Tab, NoSymbol, + XK_q, XK_Q, + XK_w, XK_W, + XK_e, XK_E, + XK_r, XK_R, + XK_t, XK_T, + XK_y, XK_Y, + XK_u, XK_U, + XK_i, XK_I, + XK_o, XK_O, + XK_p, XK_P, + XK_bracketleft, XK_braceleft, + XK_bracketright, XK_braceright, + XK_Return, NoSymbol, + XK_Control_L, NoSymbol, + XK_a, XK_A, + XK_s, XK_S, + XK_d, XK_D, + XK_f, XK_F, + XK_g, XK_G, + XK_h, XK_H, + XK_j, XK_J, + XK_k, XK_K, + XK_l, XK_L, + XK_semicolon, XK_colon, + XK_apostrophe, XK_quotedbl, + XK_grave, XK_asciitilde, + XK_Shift_L, NoSymbol, + XK_backslash, XK_bar, + XK_z, XK_Z, + XK_x, XK_X, + XK_c, XK_C, + XK_v, XK_V, + XK_b, XK_B, + XK_n, XK_N, + XK_m, XK_M, + XK_comma, XK_less, + XK_period, XK_greater, + XK_slash, XK_question, + XK_Shift_R, NoSymbol, + XK_KP_Multiply, NoSymbol, + XK_Alt_L, XK_Meta_L, + XK_space, NoSymbol, + /*XK_Caps_Lock*/ NoSymbol, NoSymbol, + XK_F1, NoSymbol, + XK_F2, NoSymbol, + XK_F3, NoSymbol, + XK_F4, NoSymbol, + XK_F5, NoSymbol, + XK_F6, NoSymbol, + XK_F7, NoSymbol, + XK_F8, NoSymbol, + XK_F9, NoSymbol, + XK_F10, NoSymbol, + XK_Num_Lock, XK_Pointer_EnableKeys, + XK_Scroll_Lock, NoSymbol, + XK_KP_Home, XK_KP_7, + XK_KP_Up, XK_KP_8, + XK_KP_Prior, XK_KP_9, + XK_KP_Subtract, NoSymbol, + XK_KP_Left, XK_KP_4, + XK_KP_Begin, XK_KP_5, + XK_KP_Right, XK_KP_6, + XK_KP_Add, NoSymbol, + XK_KP_End, XK_KP_1, + XK_KP_Down, XK_KP_2, + XK_KP_Next, XK_KP_3, + XK_KP_Insert, XK_KP_0, + XK_KP_Delete, XK_KP_Decimal, + NoSymbol, NoSymbol, + NoSymbol, NoSymbol, + NoSymbol, NoSymbol, + XK_F11, NoSymbol, + XK_F12, NoSymbol, + XK_Home, NoSymbol, + XK_Up, NoSymbol, + XK_Prior, NoSymbol, + XK_Left, NoSymbol, + NoSymbol, NoSymbol, + XK_Right, NoSymbol, + XK_End, NoSymbol, + XK_Down, NoSymbol, + XK_Next, NoSymbol, + XK_Insert, NoSymbol, + XK_Delete, NoSymbol, + XK_KP_Enter, NoSymbol, + XK_Control_R, NoSymbol, + XK_Pause, XK_Break, + XK_Print, XK_Execute, + XK_KP_Divide, NoSymbol, + XK_Alt_R, XK_Meta_R, +}; + +static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap) +{ + int i; + + for (i = 0; i < MAP_LENGTH; i++) + pModMap[i] = NoSymbol; + + for (i = 0; i < VFB_MAP_LEN; i++) { + if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock) + pModMap[i + VFB_MIN_KEY] = LockMask; + else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L || + keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R) + pModMap[i + VFB_MIN_KEY] = ShiftMask; + else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L || + keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) { + pModMap[i + VFB_MIN_KEY] = ControlMask; + } + else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L || + keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R) + pModMap[i + VFB_MIN_KEY] = Mod1Mask; + } + + pKeySyms->minKeyCode = VFB_MIN_KEY; + pKeySyms->maxKeyCode = VFB_MAX_KEY; + pKeySyms->mapWidth = KEYSYMS_PER_KEY; + pKeySyms->map = keyboardMap; + + return TRUE; +} + +static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_) +{ + if (percent > 0) + vncBell(); +} + +static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff) +{ + KeySymsRec keySyms; + CARD8 modMap[MAP_LENGTH]; + DevicePtr pDev = (DevicePtr)pDevice; + + switch (onoff) + { + case DEVICE_INIT: + GetMappings(&keySyms, modMap); + InitKeyboardDeviceStruct(pDev, &keySyms, modMap, + (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA); + break; + case DEVICE_ON: + pDev->on = TRUE; + break; + case DEVICE_OFF: + pDev->on = FALSE; + break; + case DEVICE_CLOSE: + break; + } + return Success; +} + +static int vfbMouseProc(DeviceIntPtr pDevice, int onoff) +{ + BYTE map[6]; + DevicePtr pDev = (DevicePtr)pDevice; + + switch (onoff) + { + case DEVICE_INIT: + map[1] = 1; + map[2] = 2; + map[3] = 3; + map[4] = 4; + map[5] = 5; + InitPointerDeviceStruct(pDev, map, 5, miPointerGetMotionEvents, + (PtrCtrlProcPtr)NoopDDA, miPointerGetMotionBufferSize()); + break; + + case DEVICE_ON: + pDev->on = TRUE; + break; + + case DEVICE_OFF: + pDev->on = FALSE; + break; + + case DEVICE_CLOSE: + break; + } + return Success; +} + +// InitInput is called after InitExtensions, so we're guaranteed that +// vncExtensionInit() has already been called. + +void InitInput(int argc, char *argv[]) +{ + DeviceIntPtr p, k; + p = AddInputDevice(vfbMouseProc, TRUE); + k = AddInputDevice(vfbKeybdProc, TRUE); + RegisterPointerDevice(p); + RegisterKeyboardDevice(k); + miRegisterPointerDevice(screenInfo.screens[0], p); + (void)mieqInit ((DevicePtr)k, (DevicePtr)p); +} diff --git a/unix/xc/programs/Xserver/vnc/module/Imakefile b/unix/xc/programs/Xserver/vnc/module/Imakefile new file mode 100644 index 00000000..f279649c --- /dev/null +++ b/unix/xc/programs/Xserver/vnc/module/Imakefile @@ -0,0 +1,60 @@ + + VNCTOP = $(TOP)/.. + VNCLIBS = VncExtLibs + VNCINCLUDE = -I$(VNCTOP) -I$(VNCTOP)/vncconfig_unix + +#define CplusplusSource + +#define IHaveModules +#include + + SRCS = vncExtInit.cc vncHooks.cc xf86vncModule.cc XserverDesktop.cc + OBJS = vncExtInit.o vncHooks.o xf86vncModule.o XserverDesktop.o +INCLUDES = -I.. -I../../include -I$(EXTINCSRC) -I$(XINCLUDESRC) \ + -I$(FONTINCSRC) -I$(XF86COMSRC) \ + -I../../render $(VNCINCLUDE) + DEFINES = $(STD_DEFINES) -DGC_HAS_COMPOSITE_CLIP -DXFree86LOADER + +LinkSourceFile(vncExtInit.cc,..) +LinkSourceFile(vncHooks.cc,..) +LinkSourceFile(xf86vncModule.cc,..) +LinkSourceFile(XserverDesktop.cc,..) + +ModuleObjectRule() +/* + LibraryModuleTarget(vnc,$(OBJS) $(VNCLIBS)) + InstallLibraryModule(vnc,$(MODULEDIR),extensions) +*/ + +/* *** The imake rules don't define a ModuleCplusplusObjectRule so + for now we just assume that NormalCplusplusObjectRule will + do the job. + NB: If we don't do this then make will assume CC is the C++ compiler! +*/ +NormalCplusplusObjectRule() + +/* + * CplusplusDynamicModuleTarget - build a module to be dynamically loaded + */ +#ifndef CplusplusDynamicModuleTarget +#define CplusplusDynamicModuleTarget(module,modlist) @@\ +AllTarget(module) @@\ + @@\ +module: modlist @@\ + RemoveFile($@) @@\ + $(CXX) -o $@ $(SHLIBLDFLAGS) modlist @@\ + @@\ +clean:: @@\ + RemoveFile(module) +#endif /* CplusplusDynamicModuleTarget */ + + + +CplusplusDynamicModuleTarget(vnc.so,$(OBJS) $(VNCLIBS)) +InstallDynamicModule(vnc.so,$(MODULEDIR),extensions) + +DependTarget() + +/* + InstallDriverSDKLibraryModule(vnc,$(DRIVERSDKMODULEDIR),extensions) +*/ diff --git a/unix/xc/programs/Xserver/vnc/vncExtInit.cc b/unix/xc/programs/Xserver/vnc/vncExtInit.cc new file mode 100644 index 00000000..9cf9d21b --- /dev/null +++ b/unix/xc/programs/Xserver/vnc/vncExtInit.cc @@ -0,0 +1,866 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include + +extern "C" { +#define class c_class +#define NEED_EVENTS +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "scrnintstr.h" +#include "selection.h" +#define _VNCEXT_SERVER_ +#define _VNCEXT_PROTO_ +#include "vncExt.h" +#undef class +#undef xalloc +} + +#include +#include +#include +#include +#include +#include +#include +#include +#undef max +#undef min +#include + +#include "XserverDesktop.h" +#include "vncHooks.h" +#include "vncExtInit.h" + +extern "C" { + + extern void vncExtensionInit(); + static void vncResetProc(ExtensionEntry* extEntry); + static void vncBlockHandler(pointer data, OSTimePtr t, pointer readmask); + static void vncWakeupHandler(pointer data, int nfds, pointer readmask); + static void vncClientStateChange(CallbackListPtr*, pointer, pointer); + static void SendSelectionChangeEvent(Atom selection); + static int ProcVncExtDispatch(ClientPtr client); + static int SProcVncExtDispatch(ClientPtr client); + + extern char *display; + + extern Selection *CurrentSelections; + extern int NumCurrentSelections; +} + +using namespace rfb; + +static rfb::LogWriter vlog("vncext"); + +static unsigned long vncExtGeneration = 0; +static bool initialised = false; +static XserverDesktop* desktop[MAXSCREENS] = { 0, }; +void* vncFbptr[MAXSCREENS] = { 0, }; + +static char* clientCutText = 0; +static int clientCutTextLen = 0; + +static XserverDesktop* queryConnectDesktop = 0; +static void* queryConnectId = 0; +static int queryConnectTimeout = 0; +static OsTimerPtr queryConnectTimer = 0; + +static struct VncInputSelect* vncInputSelectHead = 0; +struct VncInputSelect { + VncInputSelect(ClientPtr c, Window w, int m) : client(c), window(w), mask(m) + { + next = vncInputSelectHead; + vncInputSelectHead = this; + } + ClientPtr client; + Window window; + int mask; + VncInputSelect* next; +}; + +static int nPrevSelections = 0; +static TimeStamp* prevSelectionTimes = 0; + +static int vncErrorBase = 0; +static int vncEventBase = 0; +static char* vncPasswdFile = 0; +int vncInetdSock = -1; + +rfb::AliasParameter rfbauth("rfbauth", "Alias for PasswordFile", + &SSecurityFactoryStandard::vncAuthPasswdFile); +rfb::StringParameter httpDir("httpd", + "Directory containing files to serve via HTTP", + ""); +rfb::IntParameter httpPort("httpPort", "TCP port to listen for HTTP",0); +rfb::AliasParameter rfbwait("rfbwait", "Alias for ClientWaitTimeMillis", + &rfb::Server::clientWaitTimeMillis); +rfb::IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",0); +rfb::StringParameter desktopName("desktop", "Name of VNC desktop","x11"); +rfb::BoolParameter localhostOnly("localhost", + "Only allow connections from localhost", + false); + +void vncExtensionInit() +{ + if (vncExtGeneration == serverGeneration) { + vlog.error("vncExtensionInit: called twice in same generation?"); + return; + } + vncExtGeneration = serverGeneration; + + ExtensionEntry* extEntry + = AddExtension(VNCEXTNAME, VncExtNumberEvents, VncExtNumberErrors, + ProcVncExtDispatch, SProcVncExtDispatch, vncResetProc, + StandardMinorOpcode); + if (!extEntry) { + ErrorF("vncExtInit: AddExtension failed\n"); + return; + } + + vncErrorBase = extEntry->errorBase; + vncEventBase = extEntry->eventBase; + + vlog.info("VNC extension running!"); + + if (!AddCallback(&ClientStateCallback, vncClientStateChange, 0)) { + FatalError("AddCallback failed\n"); + } + + try { + if (!initialised) { + rfb::initStdIOLoggers(); + initialised = true; + } + + for (int scr = 0; scr < screenInfo.numScreens; scr++) { + + if (!desktop[scr]) { + network::TcpListener* listener = 0; + network::TcpListener* httpListener = 0; + if (scr == 0 && vncInetdSock != -1) { + if (network::TcpSocket::isSocket(vncInetdSock) && + !network::TcpSocket::isConnected(vncInetdSock)) + { + listener = new network::TcpListener(0, 0, vncInetdSock, true); + vlog.info("inetd wait"); + } + } else { + int port = rfbport; + if (port == 0) port = 5900 + atoi(display); + port += 1000 * scr; + listener = new network::TcpListener(port, localhostOnly); + vlog.info("Listening for VNC connections on port %d",port); + CharArray httpDirStr(httpDir.getData()); + if (httpDirStr.buf[0]) { + port = httpPort; + if (port == 0) port = 5800 + atoi(display); + port += 1000 * scr; + httpListener = new network::TcpListener(port, localhostOnly); + vlog.info("Listening for HTTP connections on port %d",port); + } + } + + CharArray desktopNameStr(desktopName.getData()); + desktop[scr] = new XserverDesktop(screenInfo.screens[scr], listener, + httpListener, + desktopNameStr.buf, + vncFbptr[scr]); + vlog.info("created VNC server for screen %d", scr); + + if (scr == 0 && vncInetdSock != -1 && !listener) { + network::Socket* sock = new network::TcpSocket(vncInetdSock); + desktop[scr]->addClient(sock, false); + vlog.info("added inetd sock"); + } + + } else { + desktop[scr]->serverReset(screenInfo.screens[scr]); + } + + vncHooksInit(screenInfo.screens[scr], desktop[scr]); + } + + RegisterBlockAndWakeupHandlers(vncBlockHandler, vncWakeupHandler, 0); + + } catch (rdr::Exception& e) { + vlog.error("vncExtInit: %s",e.str()); + } +} + +static void vncResetProc(ExtensionEntry* extEntry) +{ +} + +// +// vncBlockHandler - called just before the X server goes into select(). Call +// on to the block handler for each desktop. Then check whether any of the +// selections have changed, and if so, notify any interested X clients. +// + +static void vncBlockHandler(pointer data, OSTimePtr timeout, pointer readmask) +{ + fd_set* fds = (fd_set*)readmask; + + for (int scr = 0; scr < screenInfo.numScreens; scr++) { + if (desktop[scr]) { + desktop[scr]->blockHandler(fds); + } + } + + if (nPrevSelections != NumCurrentSelections) { + prevSelectionTimes + = (TimeStamp*)xnfrealloc(prevSelectionTimes, + NumCurrentSelections * sizeof(TimeStamp)); + for (int i = nPrevSelections; i < NumCurrentSelections; i++) { + prevSelectionTimes[i].months = 0; + prevSelectionTimes[i].milliseconds = 0; + } + nPrevSelections = NumCurrentSelections; + } + for (int i = 0; i < NumCurrentSelections; i++) { + if (CurrentSelections[i].lastTimeChanged.months + != prevSelectionTimes[i].months || + CurrentSelections[i].lastTimeChanged.milliseconds + != prevSelectionTimes[i].milliseconds) + { + SendSelectionChangeEvent(CurrentSelections[i].selection); + prevSelectionTimes[i] = CurrentSelections[i].lastTimeChanged; + } + } +} + +static void vncWakeupHandler(pointer data, int nfds, pointer readmask) +{ + fd_set* fds = (fd_set*)readmask; + + for (int scr = 0; scr < screenInfo.numScreens; scr++) { + if (desktop[scr]) { + desktop[scr]->wakeupHandler(fds, nfds); + } + } +} + +static void vncClientStateChange(CallbackListPtr*, pointer, pointer p) +{ + ClientPtr client = ((NewClientInfoRec*)p)->client; + if (client->clientState == ClientStateGone) { + VncInputSelect** nextPtr = &vncInputSelectHead; + for (VncInputSelect* cur = vncInputSelectHead; cur; cur = *nextPtr) { + if (cur->client == client) { + *nextPtr = cur->next; + delete cur; + continue; + } + nextPtr = &cur->next; + } + } +} + +void vncBell() +{ + for (int scr = 0; scr < screenInfo.numScreens; scr++) { + if (desktop[scr]) { + desktop[scr]->bell(); + } + } +} + +void vncClientGone(int fd) +{ + if (fd == vncInetdSock) { + fprintf(stderr,"inetdSock client gone\n"); + GiveUp(0); + } +} + +void vncClientCutText(const char* str, int len) +{ + delete [] clientCutText; + clientCutText = new char[len]; + memcpy(clientCutText, str, len); + clientCutTextLen = len; + xVncExtClientCutTextNotifyEvent ev; + ev.type = vncEventBase + VncExtClientCutTextNotify; + for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) { + if (cur->mask & VncExtClientCutTextMask) { + ev.sequenceNumber = cur->client->sequence; + ev.window = cur->window; + ev.time = GetTimeInMillis(); + if (cur->client->swapped) { + int n; + swaps(&ev.sequenceNumber, n); + swapl(&ev.window, n); + swapl(&ev.time, n); + } + WriteToClient(cur->client, sizeof(xVncExtClientCutTextNotifyEvent), + (char *)&ev); + } + } +} + + +static CARD32 queryConnectTimerCallback(OsTimerPtr timer, + CARD32 now, pointer arg) +{ + if (queryConnectTimeout) + queryConnectDesktop->approveConnection(queryConnectId, false, "The attempt to prompt the user to accept the connection failed"); + // Re-notify clients, causing them to discover that we're done + vncQueryConnect(queryConnectDesktop, queryConnectId); + return 0; +} + +void vncQueryConnect(XserverDesktop* desktop, void* opaqueId) +{ + // Only one query can be processed at any one time + if (queryConnectTimeout && ((desktop != queryConnectDesktop) || + (opaqueId != queryConnectId))) { + desktop->approveConnection(opaqueId, false, + "Another connection is currently being queried."); + return; + } + + // Get the query timeout. If it's zero, there is no query. + queryConnectTimeout = desktop->getQueryTimeout(opaqueId); + queryConnectId = queryConnectTimeout ? opaqueId : 0; + queryConnectDesktop = queryConnectTimeout ? desktop : 0; + + // Notify clients + bool notified = false; + xVncExtQueryConnectNotifyEvent ev; + ev.type = vncEventBase + VncExtQueryConnectNotify; + for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) { + if (cur->mask & VncExtQueryConnectMask) { + ev.sequenceNumber = cur->client->sequence; + ev.window = cur->window; + if (cur->client->swapped) { + int n; + swaps(&ev.sequenceNumber, n); + swapl(&ev.window, n); + } + WriteToClient(cur->client, sizeof(xVncExtQueryConnectNotifyEvent), + (char *)&ev); + notified = true; + } + } + + // If we're being asked to query a connection (rather than to cancel + // a query), and haven't been able to notify clients then reject it. + if (queryConnectTimeout && !notified) { + queryConnectTimeout = 0; + queryConnectId = 0; + queryConnectDesktop = 0; + desktop->approveConnection(opaqueId, false, + "Unable to query the local user to accept the connection."); + return; + } + + // Set a timer so that if no-one ever responds, we will eventually + // reject the connection + // NB: We don't set a timer if sock is null, since that indicates + // that pending queries should be cancelled. + if (queryConnectDesktop) + queryConnectTimer = TimerSet(queryConnectTimer, 0, + queryConnectTimeout*2000, + queryConnectTimerCallback, 0); + else + TimerCancel(queryConnectTimer); +} + +static void SendSelectionChangeEvent(Atom selection) +{ + xVncExtSelectionChangeNotifyEvent ev; + ev.type = vncEventBase + VncExtSelectionChangeNotify; + for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) { + if (cur->mask & VncExtSelectionChangeMask) { + ev.sequenceNumber = cur->client->sequence; + ev.window = cur->window; + ev.selection = selection; + if (cur->client->swapped) { + int n; + swaps(&ev.sequenceNumber, n); + swapl(&ev.window, n); + swapl(&ev.selection, n); + } + WriteToClient(cur->client, sizeof(xVncExtSelectionChangeNotifyEvent), + (char *)&ev); + } + } +} + +static int ProcVncExtSetParam(ClientPtr client) +{ + REQUEST(xVncExtSetParamReq); + REQUEST_FIXED_SIZE(xVncExtSetParamReq, stuff->paramLen); + CharArray param(stuff->paramLen+1); + strncpy(param.buf, (char*)&stuff[1], stuff->paramLen); + param.buf[stuff->paramLen] = 0; + + xVncExtSetParamReply rep; + int n; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.success = rfb::Configuration::setParam(param.buf); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof(xVncExtSetParamReply), (char *)&rep); + return (client->noClientException); +} + +static int SProcVncExtSetParam(ClientPtr client) +{ + register char n; + REQUEST(xVncExtSetParamReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xVncExtSetParamReq); + return ProcVncExtSetParam(client); +} + +static int ProcVncExtGetParam(ClientPtr client) +{ + REQUEST(xVncExtGetParamReq); + REQUEST_FIXED_SIZE(xVncExtGetParamReq, stuff->paramLen); + CharArray param(stuff->paramLen+1); + strncpy(param.buf, (char*)&stuff[1], stuff->paramLen); + param.buf[stuff->paramLen] = 0; + + xVncExtGetParamReply rep; + int n; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.success = 0; + int len = 0; + char* value = 0; + rfb::VoidParameter* p = rfb::Configuration::getParam(param.buf); + // Hack to avoid exposing password! + if (strcasecmp(param.buf, "Password") == 0) + p = 0; + if (p) { + value = p->getValueStr(); + rep.success = 1; + len = value ? strlen(value) : 0; + } + rep.length = (len + 3) >> 2; + rep.valueLen = len; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.valueLen, n); + } + WriteToClient(client, sizeof(xVncExtGetParamReply), (char *)&rep); + if (value) + WriteToClient(client, len, value); + delete [] value; + return (client->noClientException); +} + +static int SProcVncExtGetParam(ClientPtr client) +{ + register char n; + REQUEST(xVncExtGetParamReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xVncExtGetParamReq); + return ProcVncExtGetParam(client); +} + +static int ProcVncExtGetParamDesc(ClientPtr client) +{ + REQUEST(xVncExtGetParamDescReq); + REQUEST_FIXED_SIZE(xVncExtGetParamDescReq, stuff->paramLen); + CharArray param(stuff->paramLen+1); + strncpy(param.buf, (char*)&stuff[1], stuff->paramLen); + param.buf[stuff->paramLen] = 0; + + xVncExtGetParamDescReply rep; + int n; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.success = 0; + int len = 0; + const char* desc = 0; + rfb::VoidParameter* p = rfb::Configuration::getParam(param.buf); + if (p) { + desc = p->getDescription(); + rep.success = 1; + len = desc ? strlen(desc) : 0; + } + rep.length = (len + 3) >> 2; + rep.descLen = len; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.descLen, n); + } + WriteToClient(client, sizeof(xVncExtGetParamDescReply), (char *)&rep); + if (desc) + WriteToClient(client, len, (char*)desc); + return (client->noClientException); +} + +static int SProcVncExtGetParamDesc(ClientPtr client) +{ + register char n; + REQUEST(xVncExtGetParamDescReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xVncExtGetParamDescReq); + return ProcVncExtGetParamDesc(client); +} + +static int ProcVncExtListParams(ClientPtr client) +{ + REQUEST(xVncExtListParamsReq); + REQUEST_SIZE_MATCH(xVncExtListParamsReq); + + xVncExtListParamsReply rep; + int n; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + + int nParams = 0; + int len = 0; + for (ParameterIterator i(Configuration::global()); i.param; i.next()) { + int l = strlen(i.param->getName()); + if (l <= 255) { + nParams++; + len += l + 1; + } + } + rep.length = (len + 3) >> 2; + rep.nParams = nParams; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.nParams, n); + } + WriteToClient(client, sizeof(xVncExtListParamsReply), (char *)&rep); + rdr::U8* data = new rdr::U8[len]; + rdr::U8* ptr = data; + for (ParameterIterator i(Configuration::global()); i.param; i.next()) { + int l = strlen(i.param->getName()); + if (l <= 255) { + *ptr++ = l; + memcpy(ptr, i.param->getName(), l); + ptr += l; + } + } + WriteToClient(client, len, (char*)data); + delete [] data; + return (client->noClientException); +} + +static int SProcVncExtListParams(ClientPtr client) +{ + register char n; + REQUEST(xVncExtListParamsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xVncExtListParamsReq); + return ProcVncExtListParams(client); +} + +static int ProcVncExtSetServerCutText(ClientPtr client) +{ + REQUEST(xVncExtSetServerCutTextReq); + REQUEST_FIXED_SIZE(xVncExtSetServerCutTextReq, stuff->textLen); + char* str = new char[stuff->textLen+1]; + strncpy(str, (char*)&stuff[1], stuff->textLen); + str[stuff->textLen] = 0; + for (int scr = 0; scr < screenInfo.numScreens; scr++) { + if (desktop[scr]) { + desktop[scr]->serverCutText(str, stuff->textLen); + } + } + delete [] str; + return (client->noClientException); +} + +static int SProcVncExtSetServerCutText(ClientPtr client) +{ + register char n; + REQUEST(xVncExtSetServerCutTextReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xVncExtSetServerCutTextReq); + swapl(&stuff->textLen, n); + return ProcVncExtSetServerCutText(client); +} + +static int ProcVncExtGetClientCutText(ClientPtr client) +{ + REQUEST(xVncExtGetClientCutTextReq); + REQUEST_SIZE_MATCH(xVncExtGetClientCutTextReq); + + xVncExtGetClientCutTextReply rep; + int n; + rep.type = X_Reply; + rep.length = (clientCutTextLen + 3) >> 2; + rep.sequenceNumber = client->sequence; + rep.textLen = clientCutTextLen; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.textLen, n); + } + WriteToClient(client, sizeof(xVncExtGetClientCutTextReply), (char *)&rep); + if (clientCutText) + WriteToClient(client, clientCutTextLen, clientCutText); + return (client->noClientException); +} + +static int SProcVncExtGetClientCutText(ClientPtr client) +{ + register char n; + REQUEST(xVncExtGetClientCutTextReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xVncExtGetClientCutTextReq); + return ProcVncExtGetClientCutText(client); +} + +static int ProcVncExtSelectInput(ClientPtr client) +{ + REQUEST(xVncExtSelectInputReq); + REQUEST_SIZE_MATCH(xVncExtSelectInputReq); + VncInputSelect** nextPtr = &vncInputSelectHead; + VncInputSelect* cur; + for (cur = vncInputSelectHead; cur; cur = *nextPtr) { + if (cur->client == client && cur->window == stuff->window) { + cur->mask = stuff->mask; + if (!cur->mask) { + *nextPtr = cur->next; + delete cur; + } + break; + } + nextPtr = &cur->next; + } + if (!cur) { + cur = new VncInputSelect(client, stuff->window, stuff->mask); + } + return (client->noClientException); +} + +static int SProcVncExtSelectInput(ClientPtr client) +{ + register char n; + REQUEST(xVncExtSelectInputReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xVncExtSelectInputReq); + swapl(&stuff->window, n); + swapl(&stuff->mask, n); + return ProcVncExtSelectInput(client); +} + +static int ProcVncExtConnect(ClientPtr client) +{ + REQUEST(xVncExtConnectReq); + REQUEST_FIXED_SIZE(xVncExtConnectReq, stuff->strLen); + CharArray str(stuff->strLen+1); + strncpy(str.buf, (char*)&stuff[1], stuff->strLen); + str.buf[stuff->strLen] = 0; + + xVncExtConnectReply rep; + rep.success = 0; + if (desktop[0]) { + if (stuff->strLen == 0) { + try { + desktop[0]->disconnectClients(); + rep.success = 1; + } catch (rdr::Exception& e) { + vlog.error("Disconnecting all clients: %s",e.str()); + } + } else { + int port = 5500; + for (int i = 0; i < stuff->strLen; i++) { + if (str.buf[i] == ':') { + port = atoi(&str.buf[i+1]); + str.buf[i] = 0; + break; + } + } + + try { + network::Socket* sock = new network::TcpSocket(str.buf, port); + desktop[0]->addClient(sock, true); + rep.success = 1; + } catch (rdr::Exception& e) { + vlog.error("Reverse connection: %s",e.str()); + } + } + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (client->swapped) { + int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof(xVncExtConnectReply), (char *)&rep); + return (client->noClientException); +} + +static int SProcVncExtConnect(ClientPtr client) +{ + register char n; + REQUEST(xVncExtConnectReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xVncExtConnectReq); + return ProcVncExtConnect(client); +} + + +static int ProcVncExtGetQueryConnect(ClientPtr client) +{ + REQUEST(xVncExtGetQueryConnectReq); + REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq); + + const char *qcAddress=0, *qcUsername=0; + int qcTimeout; + if (queryConnectDesktop) + qcTimeout = queryConnectDesktop->getQueryTimeout(queryConnectId, + &qcAddress, &qcUsername); + else + qcTimeout = 0; + + xVncExtGetQueryConnectReply rep; + int n; + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.timeout = qcTimeout; + rep.addrLen = qcTimeout ? strlen(qcAddress) : 0; + rep.userLen = qcTimeout ? strlen(qcUsername) : 0; + rep.opaqueId = (CARD32)queryConnectId; + rep.length = (rep.userLen + rep.addrLen + 3) >> 2; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.userLen, n); + swapl(&rep.addrLen, n); + swapl(&rep.timeout, n); + swapl(&rep.opaqueId, n); + } + WriteToClient(client, sizeof(xVncExtGetQueryConnectReply), (char *)&rep); + if (qcTimeout) + WriteToClient(client, strlen(qcAddress), (char*)qcAddress); + if (qcTimeout) + WriteToClient(client, strlen(qcUsername), (char*)qcUsername); + return (client->noClientException); +} + +static int SProcVncExtGetQueryConnect(ClientPtr client) +{ + register char n; + REQUEST(xVncExtGetQueryConnectReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq); + return ProcVncExtGetQueryConnect(client); +} + + +static int ProcVncExtApproveConnect(ClientPtr client) +{ + REQUEST(xVncExtApproveConnectReq); + REQUEST_SIZE_MATCH(xVncExtApproveConnectReq); + if (queryConnectId == (void*)stuff->opaqueId) { + for (int scr = 0; scr < screenInfo.numScreens; scr++) { + if (desktop[scr]) { + desktop[scr]->approveConnection(queryConnectId, stuff->approve, + "Connection rejected by local user"); + } + } + // Inform other clients of the event and tidy up + vncQueryConnect(queryConnectDesktop, queryConnectId); + } + return (client->noClientException); +} + +static int SProcVncExtApproveConnect(ClientPtr client) +{ + register char n; + REQUEST(xVncExtApproveConnectReq); + swaps(&stuff->length, n); + swapl(&stuff->opaqueId, n); + REQUEST_SIZE_MATCH(xVncExtApproveConnectReq); + return ProcVncExtApproveConnect(client); +} + + +static int ProcVncExtDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_VncExtSetParam: + return ProcVncExtSetParam(client); + case X_VncExtGetParam: + return ProcVncExtGetParam(client); + case X_VncExtGetParamDesc: + return ProcVncExtGetParamDesc(client); + case X_VncExtListParams: + return ProcVncExtListParams(client); + case X_VncExtSetServerCutText: + return ProcVncExtSetServerCutText(client); + case X_VncExtGetClientCutText: + return ProcVncExtGetClientCutText(client); + case X_VncExtSelectInput: + return ProcVncExtSelectInput(client); + case X_VncExtConnect: + return ProcVncExtConnect(client); + case X_VncExtGetQueryConnect: + return ProcVncExtGetQueryConnect(client); + case X_VncExtApproveConnect: + return ProcVncExtApproveConnect(client); + default: + return BadRequest; + } +} + +static int SProcVncExtDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_VncExtSetParam: + return SProcVncExtSetParam(client); + case X_VncExtGetParam: + return SProcVncExtGetParam(client); + case X_VncExtGetParamDesc: + return SProcVncExtGetParamDesc(client); + case X_VncExtListParams: + return SProcVncExtListParams(client); + case X_VncExtSetServerCutText: + return SProcVncExtSetServerCutText(client); + case X_VncExtGetClientCutText: + return SProcVncExtGetClientCutText(client); + case X_VncExtSelectInput: + return SProcVncExtSelectInput(client); + case X_VncExtConnect: + return SProcVncExtConnect(client); + case X_VncExtGetQueryConnect: + return SProcVncExtGetQueryConnect(client); + case X_VncExtApproveConnect: + return SProcVncExtApproveConnect(client); + default: + return BadRequest; + } +} + diff --git a/unix/xc/programs/Xserver/vnc/vncExtInit.h b/unix/xc/programs/Xserver/vnc/vncExtInit.h new file mode 100644 index 00000000..45453e1f --- /dev/null +++ b/unix/xc/programs/Xserver/vnc/vncExtInit.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#ifndef __VNCEXTINIT_H__ +#define __VNCEXTINIT_H__ + +#include +#include "XserverDesktop.h" + +extern void vncClientCutText(const char* str, int len); +extern void vncQueryConnect(XserverDesktop* desktop, void* opaqueId); +extern void vncClientGone(int fd); +extern void vncBell(); +extern void* vncFbptr[]; +extern int vncInetdSock; +extern rfb::StringParameter httpDir; + +#endif diff --git a/unix/xc/programs/Xserver/vnc/vncHooks.cc b/unix/xc/programs/Xserver/vnc/vncHooks.cc new file mode 100644 index 00000000..ce8e7f02 --- /dev/null +++ b/unix/xc/programs/Xserver/vnc/vncHooks.cc @@ -0,0 +1,1533 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include "XserverDesktop.h" +#include "vncHooks.h" + +extern "C" { +#define class c_class +#define private c_private +#include "scrnintstr.h" +#include "windowstr.h" +#include "gcstruct.h" +#include "regionstr.h" +#include "dixfontstr.h" +#include "colormapst.h" +#ifdef RENDER +#include "picturestr.h" +#endif + +#ifdef GC_HAS_COMPOSITE_CLIP +#define COMPOSITE_CLIP(gc) ((gc)->pCompositeClip) +#else +#include "mfb.h" +#define COMPOSITE_CLIP(gc) \ + (((mfbPrivGCPtr)((gc)->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip) +#endif + +#undef class +#undef private +} + +#include "RegionHelper.h" + +#define DBGPRINT(x) //(fprintf x) + +// MAX_RECTS_PER_OP is the maximum number of rectangles we generate from +// operations like Polylines and PolySegment. If the operation is more complex +// than this, we simply use the bounding box. Ideally it would be a +// command-line option, but that would involve an extra malloc each time, so we +// fix it here. +#define MAX_RECTS_PER_OP 5 + +static unsigned long vncHooksGeneration = 0; + +// vncHooksScreenRec and vncHooksGCRec contain pointers to the original +// functions which we "wrap" in order to hook the screen changes. The screen +// functions are each wrapped individually, while the GC "funcs" and "ops" are +// wrapped as a unit. + +typedef struct { + XserverDesktop* desktop; + + CloseScreenProcPtr CloseScreen; + CreateGCProcPtr CreateGC; + PaintWindowBackgroundProcPtr PaintWindowBackground; + PaintWindowBorderProcPtr PaintWindowBorder; + CopyWindowProcPtr CopyWindow; + ClearToBackgroundProcPtr ClearToBackground; + RestoreAreasProcPtr RestoreAreas; + InstallColormapProcPtr InstallColormap; + StoreColorsProcPtr StoreColors; + DisplayCursorProcPtr DisplayCursor; + ScreenBlockHandlerProcPtr BlockHandler; +#ifdef RENDER + CompositeProcPtr Composite; +#endif +} vncHooksScreenRec, *vncHooksScreenPtr; + +typedef struct { + GCFuncs *wrappedFuncs; + GCOps *wrappedOps; +} vncHooksGCRec, *vncHooksGCPtr; + +static int vncHooksScreenIndex; +static int vncHooksGCIndex; + + +// screen functions + +static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen); +static Bool vncHooksCreateGC(GCPtr pGC); +static void vncHooksPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion, + int what); +static void vncHooksPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, + int what); +static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, + RegionPtr pOldRegion); +static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w, + int h, Bool generateExposures); +static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed); +static void vncHooksInstallColormap(ColormapPtr pColormap); +static void vncHooksStoreColors(ColormapPtr pColormap, int ndef, + xColorItem* pdef); +static Bool vncHooksDisplayCursor(ScreenPtr pScreen, CursorPtr cursor); +static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout, + pointer pReadmask); +#ifdef RENDER +static void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, + PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, + INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); +#endif + +// GC "funcs" + +static void vncHooksValidateGC(GCPtr pGC, unsigned long changes, + DrawablePtr pDrawable); +static void vncHooksChangeGC(GCPtr pGC, unsigned long mask); +static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst); +static void vncHooksDestroyGC(GCPtr pGC); +static void vncHooksChangeClip(GCPtr pGC, int type, pointer pValue,int nrects); +static void vncHooksDestroyClip(GCPtr pGC); +static void vncHooksCopyClip(GCPtr dst, GCPtr src); + +static GCFuncs vncHooksGCFuncs = { + vncHooksValidateGC, vncHooksChangeGC, vncHooksCopyGC, vncHooksDestroyGC, + vncHooksChangeClip, vncHooksDestroyClip, vncHooksCopyClip, +}; + +// GC "ops" + +static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit, + DDXPointPtr pptInit, int *pwidthInit, + int fSorted); +static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc, + DDXPointPtr ppt, int *pwidth, int nspans, + int fSorted); +static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, + int format, char *pBits); +static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst, + GCPtr pGC, int srcx, int srcy, int w, int h, + int dstx, int dsty); +static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, + GCPtr pGC, int srcx, int srcy, int w, int h, + int dstx, int dsty, unsigned long plane); +static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, xPoint *pts); +static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr ppts); +static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, + xSegment *segs); +static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, + xRectangle *rects); +static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, + xArc *arcs); +static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr pts); +static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects, + xRectangle *rects); +static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, + xArc *arcs); +static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int count, char *chars); +static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int count, unsigned short *chars); +static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int count, char *chars); +static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int count, unsigned short *chars); +static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, unsigned int nglyph, + CharInfoPtr *ppci, pointer pglyphBase); +static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, unsigned int nglyph, + CharInfoPtr *ppci, pointer pglyphBase); +static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap, + DrawablePtr pDrawable, int w, int h, int x, + int y); + +static GCOps vncHooksGCOps = { + vncHooksFillSpans, vncHooksSetSpans, vncHooksPutImage, vncHooksCopyArea, + vncHooksCopyPlane, vncHooksPolyPoint, vncHooksPolylines, vncHooksPolySegment, + vncHooksPolyRectangle, vncHooksPolyArc, vncHooksFillPolygon, + vncHooksPolyFillRect, vncHooksPolyFillArc, vncHooksPolyText8, + vncHooksPolyText16, vncHooksImageText8, vncHooksImageText16, + vncHooksImageGlyphBlt, vncHooksPolyGlyphBlt, vncHooksPushPixels +}; + + + +///////////////////////////////////////////////////////////////////////////// +// vncHooksInit() is called at initialisation time and every time the server +// resets. It is called once for each screen, but the indexes are only +// allocated once for each server generation. + +Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop) +{ + vncHooksScreenPtr vncHooksScreen; + + if (vncHooksGeneration != serverGeneration) { + vncHooksGeneration = serverGeneration; + + vncHooksScreenIndex = AllocateScreenPrivateIndex(); + if (vncHooksScreenIndex < 0) { + ErrorF("vncHooksInit: AllocateScreenPrivateIndex failed\n"); + return FALSE; + } + + vncHooksGCIndex = AllocateGCPrivateIndex(); + if (vncHooksGCIndex < 0) { + ErrorF("vncHooksInit: AllocateGCPrivateIndex failed\n"); + return FALSE; + } + } + + if (!AllocateGCPrivate(pScreen, vncHooksGCIndex, sizeof(vncHooksGCRec))) { + ErrorF("vncHooksInit: AllocateGCPrivate failed\n"); + return FALSE; + } + + vncHooksScreen = (vncHooksScreenPtr)xnfalloc(sizeof(vncHooksScreenRec)); + pScreen->devPrivates[vncHooksScreenIndex].ptr = (pointer)vncHooksScreen; + + vncHooksScreen->desktop = desktop; + + vncHooksScreen->CloseScreen = pScreen->CloseScreen; + vncHooksScreen->CreateGC = pScreen->CreateGC; + vncHooksScreen->PaintWindowBackground = pScreen->PaintWindowBackground; + vncHooksScreen->PaintWindowBorder = pScreen->PaintWindowBorder; + vncHooksScreen->CopyWindow = pScreen->CopyWindow; + vncHooksScreen->ClearToBackground = pScreen->ClearToBackground; + vncHooksScreen->RestoreAreas = pScreen->RestoreAreas; + vncHooksScreen->InstallColormap = pScreen->InstallColormap; + vncHooksScreen->StoreColors = pScreen->StoreColors; + vncHooksScreen->DisplayCursor = pScreen->DisplayCursor; + vncHooksScreen->BlockHandler = pScreen->BlockHandler; +#ifdef RENDER + PictureScreenPtr ps; + ps = GetPictureScreenIfSet(pScreen); + if (ps) { + vncHooksScreen->Composite = ps->Composite; + } +#endif + + pScreen->CloseScreen = vncHooksCloseScreen; + pScreen->CreateGC = vncHooksCreateGC; + pScreen->PaintWindowBackground = vncHooksPaintWindowBackground; + pScreen->PaintWindowBorder = vncHooksPaintWindowBorder; + pScreen->CopyWindow = vncHooksCopyWindow; + pScreen->ClearToBackground = vncHooksClearToBackground; + pScreen->RestoreAreas = vncHooksRestoreAreas; + pScreen->InstallColormap = vncHooksInstallColormap; + pScreen->StoreColors = vncHooksStoreColors; + pScreen->DisplayCursor = vncHooksDisplayCursor; + pScreen->BlockHandler = vncHooksBlockHandler; +#ifdef RENDER + if (ps) { + ps->Composite = vncHooksComposite; + } +#endif + + return TRUE; +} + + + +///////////////////////////////////////////////////////////////////////////// +// +// screen functions +// + +// SCREEN_UNWRAP and SCREEN_REWRAP unwrap and rewrap the given screen function. +// It would be nice to do this with a C++ class, but each function is of a +// distinct type, so it would have to use templates, and it's not worth that +// much pain. + +#define SCREEN_UNWRAP(scrn,field) \ + ScreenPtr pScreen = scrn; \ + vncHooksScreenPtr vncHooksScreen \ + = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr); \ + pScreen->field = vncHooksScreen->field; \ + DBGPRINT((stderr,"vncHooks" #field " called\n")); + +#define SCREEN_REWRAP(field) pScreen->field = vncHooks##field; + + +// CloseScreen - unwrap the screen functions and call the original CloseScreen +// function + +static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen_) +{ + SCREEN_UNWRAP(pScreen_, CloseScreen); + + pScreen->CreateGC = vncHooksScreen->CreateGC; + pScreen->PaintWindowBackground = vncHooksScreen->PaintWindowBackground; + pScreen->PaintWindowBorder = vncHooksScreen->PaintWindowBorder; + pScreen->CopyWindow = vncHooksScreen->CopyWindow; + pScreen->ClearToBackground = vncHooksScreen->ClearToBackground; + pScreen->RestoreAreas = vncHooksScreen->RestoreAreas; + pScreen->InstallColormap = vncHooksScreen->InstallColormap; + pScreen->StoreColors = vncHooksScreen->StoreColors; + pScreen->DisplayCursor = vncHooksScreen->DisplayCursor; + pScreen->BlockHandler = vncHooksScreen->BlockHandler; + + xfree((pointer)vncHooksScreen); + + DBGPRINT((stderr,"vncHooksCloseScreen: unwrapped screen functions\n")); + + return (*pScreen->CloseScreen)(i, pScreen); +} + +// CreateGC - wrap the "GC funcs" + +static Bool vncHooksCreateGC(GCPtr pGC) +{ + SCREEN_UNWRAP(pGC->pScreen, CreateGC); + + vncHooksGCPtr vncHooksGC + = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr; + + Bool ret = (*pScreen->CreateGC) (pGC); + + vncHooksGC->wrappedOps = 0; + vncHooksGC->wrappedFuncs = pGC->funcs; + pGC->funcs = &vncHooksGCFuncs; + + SCREEN_REWRAP(CreateGC); + + return ret; +} + +// PaintWindowBackground - changed region is the given region + +static void vncHooksPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion, + int what) +{ + SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBackground); + + RegionHelper changed(pScreen, pRegion); + + (*pScreen->PaintWindowBackground) (pWin, pRegion, what); + + vncHooksScreen->desktop->add_changed(changed.reg); + + SCREEN_REWRAP(PaintWindowBackground); +} + +// PaintWindowBorder - changed region is the given region + +static void vncHooksPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, + int what) +{ + SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBorder); + + RegionHelper changed(pScreen, pRegion); + + (*pScreen->PaintWindowBorder) (pWin, pRegion, what); + + vncHooksScreen->desktop->add_changed(changed.reg); + + SCREEN_REWRAP(PaintWindowBorder); +} + +// CopyWindow - destination of the copy is the old region, clipped by +// borderClip, translated by the delta. This call only does the copy - it +// doesn't affect any other bits. + +static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, + RegionPtr pOldRegion) +{ + SCREEN_UNWRAP(pWin->drawable.pScreen, CopyWindow); + + RegionHelper copied(pScreen, pOldRegion); + int dx = pWin->drawable.x - ptOldOrg.x; + int dy = pWin->drawable.y - ptOldOrg.y; + REGION_TRANSLATE(pScreen, copied.reg, dx, dy); + REGION_INTERSECT(pWin->drawable.pScreen, copied.reg, copied.reg, + &pWin->borderClip); + + (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion); + + vncHooksScreen->desktop->add_copied(copied.reg, dx, dy); + + SCREEN_REWRAP(CopyWindow); +} + +// ClearToBackground - changed region is the given rectangle, clipped by +// clipList, but only if generateExposures is false. + +static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w, + int h, Bool generateExposures) +{ + SCREEN_UNWRAP(pWin->drawable.pScreen, ClearToBackground); + + BoxRec box; + box.x1 = x + pWin->drawable.x; + box.y1 = y + pWin->drawable.y; + box.x2 = w ? (box.x1 + w) : (pWin->drawable.x + pWin->drawable.width); + box.y2 = h ? (box.y1 + h) : (pWin->drawable.y + pWin->drawable.height); + + RegionHelper changed(pScreen, &box, 0); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, &pWin->clipList); + + (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures); + + if (!generateExposures) { + vncHooksScreen->desktop->add_changed(changed.reg); + } + + SCREEN_REWRAP(ClearToBackground); +} + +// RestoreAreas - changed region is the given region + +static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr pRegion) +{ + SCREEN_UNWRAP(pWin->drawable.pScreen, RestoreAreas); + + RegionHelper changed(pScreen, pRegion); + + RegionPtr result = (*pScreen->RestoreAreas) (pWin, pRegion); + + vncHooksScreen->desktop->add_changed(changed.reg); + + SCREEN_REWRAP(RestoreAreas); + + return result; +} + +// InstallColormap - get the new colormap + +static void vncHooksInstallColormap(ColormapPtr pColormap) +{ + SCREEN_UNWRAP(pColormap->pScreen, InstallColormap); + + (*pScreen->InstallColormap) (pColormap); + + vncHooksScreen->desktop->setColormap(pColormap); + + SCREEN_REWRAP(InstallColormap); +} + +// StoreColors - get the colormap changes + +static void vncHooksStoreColors(ColormapPtr pColormap, int ndef, + xColorItem* pdef) +{ + SCREEN_UNWRAP(pColormap->pScreen, StoreColors); + + (*pScreen->StoreColors) (pColormap, ndef, pdef); + + vncHooksScreen->desktop->setColourMapEntries(pColormap, ndef, pdef); + + SCREEN_REWRAP(StoreColors); +} + +// DisplayCursor - get the cursor shape + +static Bool vncHooksDisplayCursor(ScreenPtr pScreen_, CursorPtr cursor) +{ + SCREEN_UNWRAP(pScreen_, DisplayCursor); + + Bool ret = (*pScreen->DisplayCursor) (pScreen, cursor); + + vncHooksScreen->desktop->setCursor(cursor); + + SCREEN_REWRAP(DisplayCursor); + + return ret; +} + +// BlockHandler - ignore any changes during the block handler - it's likely +// these are just drawing the cursor. + +static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout, + pointer pReadmask) +{ + SCREEN_UNWRAP(screenInfo.screens[i], BlockHandler); + + vncHooksScreen->desktop->ignoreHooks(true); + + (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); + + vncHooksScreen->desktop->ignoreHooks(false); + + SCREEN_REWRAP(BlockHandler); +} + +// Composite - needed for RENDER + +#ifdef RENDER +void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, + PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, + INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + vncHooksScreenPtr vncHooksScreen = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr); + BoxRec box; + PictureScreenPtr ps = GetPictureScreen(pScreen); + rfb::Rect rect1, rect2; + + rect1.setXYWH(pDst->pDrawable->x + xDst, + pDst->pDrawable->y + yDst, + width, + height); + + rect2 = rect1.intersect(vncHooksScreen->desktop->getRect()); + if (!rect2.is_empty()) { + box.x1 = rect2.tl.x; + box.y1 = rect2.tl.y; + box.x2 = rect2.br.x; + box.y2 = rect2.br.y; + RegionHelper changed(pScreen, &box, 0); + vncHooksScreen->desktop->add_changed(changed.reg); + } + + ps->Composite = vncHooksScreen->Composite; + (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc, + xMask, yMask, xDst, yDst, width, height); + ps->Composite = vncHooksComposite; +} + +#endif /* RENDER */ + + +///////////////////////////////////////////////////////////////////////////// +// +// GC "funcs" +// + +// GCFuncUnwrapper is a helper class which unwraps the GC funcs and ops in its +// constructor and rewraps them in its destructor. + +class GCFuncUnwrapper { +public: + GCFuncUnwrapper(GCPtr pGC_) : pGC(pGC_) { + vncHooksGC = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr; + pGC->funcs = vncHooksGC->wrappedFuncs; + if (vncHooksGC->wrappedOps) + pGC->ops = vncHooksGC->wrappedOps; + } + ~GCFuncUnwrapper() { + vncHooksGC->wrappedFuncs = pGC->funcs; + pGC->funcs = &vncHooksGCFuncs; + if (vncHooksGC->wrappedOps) { + vncHooksGC->wrappedOps = pGC->ops; + pGC->ops = &vncHooksGCOps; + } + } + GCPtr pGC; + vncHooksGCPtr vncHooksGC; +}; + + +// ValidateGC - wrap the "ops" if a viewable window + +static void vncHooksValidateGC(GCPtr pGC, unsigned long changes, + DrawablePtr pDrawable) +{ + GCFuncUnwrapper u(pGC); + + DBGPRINT((stderr,"vncHooksValidateGC called\n")); + + (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); + + u.vncHooksGC->wrappedOps = 0; + if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr)pDrawable)->viewable) { + WindowPtr pWin = (WindowPtr)pDrawable; + RegionPtr pRegion = &pWin->clipList; + + if (pGC->subWindowMode == IncludeInferiors) + pRegion = &pWin->borderClip; + if (REGION_NOTEMPTY(pDrawable->pScreen, pRegion)) { + u.vncHooksGC->wrappedOps = pGC->ops; + DBGPRINT((stderr,"vncHooksValidateGC: wrapped GC ops\n")); + } + } +} + +// Other GC funcs - just unwrap and call on + +static void vncHooksChangeGC(GCPtr pGC, unsigned long mask) { + GCFuncUnwrapper u(pGC); + (*pGC->funcs->ChangeGC) (pGC, mask); +} +static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst) { + GCFuncUnwrapper u(dst); + (*dst->funcs->CopyGC) (src, mask, dst); +} +static void vncHooksDestroyGC(GCPtr pGC) { + GCFuncUnwrapper u(pGC); + (*pGC->funcs->DestroyGC) (pGC); +} +static void vncHooksChangeClip(GCPtr pGC, int type, pointer pValue, int nrects) +{ + GCFuncUnwrapper u(pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pValue, nrects); +} +static void vncHooksDestroyClip(GCPtr pGC) { + GCFuncUnwrapper u(pGC); + (*pGC->funcs->DestroyClip) (pGC); +} +static void vncHooksCopyClip(GCPtr dst, GCPtr src) { + GCFuncUnwrapper u(dst); + (*dst->funcs->CopyClip) (dst, src); +} + + +///////////////////////////////////////////////////////////////////////////// +// +// GC "ops" +// + +// GCOpUnwrapper is a helper class which unwraps the GC funcs and ops in its +// constructor and rewraps them in its destructor. + +class GCOpUnwrapper { +public: + GCOpUnwrapper(DrawablePtr pDrawable, GCPtr pGC_) + : pGC(pGC_), pScreen(pDrawable->pScreen) + { + vncHooksGC = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr; + oldFuncs = pGC->funcs; + pGC->funcs = vncHooksGC->wrappedFuncs; + pGC->ops = vncHooksGC->wrappedOps; + } + ~GCOpUnwrapper() { + vncHooksGC->wrappedOps = pGC->ops; + pGC->funcs = oldFuncs; + pGC->ops = &vncHooksGCOps; + } + GCPtr pGC; + vncHooksGCPtr vncHooksGC; + GCFuncs* oldFuncs; + ScreenPtr pScreen; +}; + +#define GC_OP_UNWRAPPER(pDrawable, pGC, name) \ + GCOpUnwrapper u(pDrawable, pGC); \ + ScreenPtr pScreen = (pDrawable)->pScreen; \ + vncHooksScreenPtr vncHooksScreen \ + = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr); \ + DBGPRINT((stderr,"vncHooks" #name " called\n")); + + +// FillSpans - changed region is the whole of borderClip. This is pessimistic, +// but I believe this function is rarely used so it doesn't matter. + +static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit, + DDXPointPtr pptInit, int *pwidthInit, + int fSorted) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, FillSpans); + + RegionHelper changed(pScreen, &((WindowPtr)pDrawable)->borderClip); + + (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted); + + vncHooksScreen->desktop->add_changed(changed.reg); +} + +// SetSpans - changed region is the whole of borderClip. This is pessimistic, +// but I believe this function is rarely used so it doesn't matter. + +static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc, + DDXPointPtr ppt, int *pwidth, int nspans, + int fSorted) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, SetSpans); + + RegionHelper changed(pScreen, &((WindowPtr)pDrawable)->borderClip); + + (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); + + vncHooksScreen->desktop->add_changed(changed.reg); +} + +// PutImage - changed region is the given rectangle, clipped by pCompositeClip + +static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, + int x, int y, int w, int h, int leftPad, + int format, char *pBits) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, PutImage); + + BoxRec box; + box.x1 = x + pDrawable->x; + box.y1 = y + pDrawable->y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + + RegionHelper changed(pScreen, &box, 0); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format, + pBits); + + vncHooksScreen->desktop->add_changed(changed.reg); +} + +// CopyArea - destination of the copy is the dest rectangle, clipped by +// pCompositeClip. Any parts of the destination which cannot be copied from +// the source (could be all of it) go into the changed region. + +static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst, + GCPtr pGC, int srcx, int srcy, int w, int h, + int dstx, int dsty) +{ + GC_OP_UNWRAPPER(pDst, pGC, CopyArea); + + BoxRec box; + box.x1 = dstx + pDst->x; + box.y1 = dsty + pDst->y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + + RegionHelper dst(pScreen, &box, 0); + REGION_INTERSECT(pScreen, dst.reg, dst.reg, COMPOSITE_CLIP(pGC)); + + RegionHelper src(pScreen); + + if ((pSrc->type == DRAWABLE_WINDOW) && (pSrc->pScreen == pScreen)) { + box.x1 = srcx + pSrc->x; + box.y1 = srcy + pSrc->y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + + src.init(&box, 0); + REGION_INTERSECT(pScreen, src.reg, src.reg, &((WindowPtr)pSrc)->clipList); + REGION_TRANSLATE(pScreen, src.reg, + dstx + pDst->x - srcx - pSrc->x, + dsty + pDst->y - srcy - pSrc->y); + } else { + src.init(NullBox, 0); + } + + RegionHelper changed(pScreen, NullBox, 0); + REGION_SUBTRACT(pScreen, changed.reg, dst.reg, src.reg); + REGION_INTERSECT(pScreen, dst.reg, dst.reg, src.reg); + + RegionPtr rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, + dstx, dsty); + + if (REGION_NOTEMPTY(pScreen, dst.reg)) + vncHooksScreen->desktop->add_copied(dst.reg, + dstx + pDst->x - srcx - pSrc->x, + dsty + pDst->y - srcy - pSrc->y); + + if (REGION_NOTEMPTY(pScreen, changed.reg)) + vncHooksScreen->desktop->add_changed(changed.reg); + + return rgn; +} + + +// CopyPlane - changed region is the destination rectangle, clipped by +// pCompositeClip + +static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, + GCPtr pGC, int srcx, int srcy, int w, int h, + int dstx, int dsty, unsigned long plane) +{ + GC_OP_UNWRAPPER(pDst, pGC, CopyPlane); + + BoxRec box; + box.x1 = dstx + pDst->x; + box.y1 = dsty + pDst->y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + + RegionHelper changed(pScreen, &box, 0); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + RegionPtr rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h, + dstx, dsty, plane); + vncHooksScreen->desktop->add_changed(changed.reg); + + return rgn; +} + +// PolyPoint - changed region is the bounding rect, clipped by pCompositeClip + +static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, xPoint *pts) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, PolyPoint); + + if (npt == 0) { + (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts); + return; + } + + int minX = pts[0].x; + int maxX = pts[0].x; + int minY = pts[0].y; + int maxY = pts[0].y; + + if (mode == CoordModePrevious) { + int x = pts[0].x; + int y = pts[0].y; + + for (int i = 1; i < npt; i++) { + x += pts[i].x; + y += pts[i].y; + if (x < minX) minX = x; + if (x > maxX) maxX = x; + if (y < minY) minY = y; + if (y > maxY) maxY = y; + } + } else { + for (int i = 1; i < npt; i++) { + if (pts[i].x < minX) minX = pts[i].x; + if (pts[i].x > maxX) maxX = pts[i].x; + if (pts[i].y < minY) minY = pts[i].y; + if (pts[i].y > maxY) maxY = pts[i].y; + } + } + + BoxRec box; + box.x1 = minX + pDrawable->x; + box.y1 = minY + pDrawable->y; + box.x2 = maxX + 1 + pDrawable->x; + box.y2 = maxY + 1 + pDrawable->y; + + RegionHelper changed(pScreen, &box, 0); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts); + + vncHooksScreen->desktop->add_changed(changed.reg); +} + +// Polylines - changed region is the union of the bounding rects of each line, +// clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP lines, +// just use the bounding rect of all the lines. + +static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr ppts) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, Polylines); + + if (npt == 0) { + (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts); + return; + } + + int nRegRects = npt - 1; + xRectangle regRects[MAX_RECTS_PER_OP]; + + int lw = pGC->lineWidth; + if (lw == 0) lw = 1; + + if (npt == 1) + { + // a single point + nRegRects = 1; + regRects[0].x = pDrawable->x + ppts[0].x - lw; + regRects[0].y = pDrawable->y + ppts[0].y - lw; + regRects[0].width = 2*lw; + regRects[0].height = 2*lw; + } + else + { + /* + * mitered joins can project quite a way from + * the line end; the 11 degree miter limit limits + * this extension to lw / (2 * tan(11/2)), rounded up + * and converted to int yields 6 * lw + */ + + int extra = lw / 2; + if (pGC->joinStyle == JoinMiter) { + extra = 6 * lw; + } + + int prevX, prevY, curX, curY; + int rectX1, rectY1, rectX2, rectY2; + int minX, minY, maxX, maxY; + + prevX = ppts[0].x + pDrawable->x; + prevY = ppts[0].y + pDrawable->y; + minX = maxX = prevX; + minY = maxY = prevY; + + for (int i = 0; i < nRegRects; i++) { + if (mode == CoordModeOrigin) { + curX = pDrawable->x + ppts[i+1].x; + curY = pDrawable->y + ppts[i+1].y; + } else { + curX = prevX + ppts[i+1].x; + curY = prevY + ppts[i+1].y; + } + + if (prevX > curX) { + rectX1 = curX - extra; + rectX2 = prevX + extra + 1; + } else { + rectX1 = prevX - extra; + rectX2 = curX + extra + 1; + } + + if (prevY > curY) { + rectY1 = curY - extra; + rectY2 = prevY + extra + 1; + } else { + rectY1 = prevY - extra; + rectY2 = curY + extra + 1; + } + + if (nRegRects <= MAX_RECTS_PER_OP) { + regRects[i].x = rectX1; + regRects[i].y = rectY1; + regRects[i].width = rectX2 - rectX1; + regRects[i].height = rectY2 - rectY1; + } else { + if (rectX1 < minX) minX = rectX1; + if (rectY1 < minY) minY = rectY1; + if (rectX2 > maxX) maxX = rectX2; + if (rectY2 > maxY) maxY = rectY2; + } + + prevX = curX; + prevY = curY; + } + + if (nRegRects > MAX_RECTS_PER_OP) { + regRects[0].x = minX; + regRects[0].y = minY; + regRects[0].width = maxX - minX; + regRects[0].height = maxY - minY; + nRegRects = 1; + } + } + + RegionHelper changed(pScreen, nRegRects, regRects); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts); + + vncHooksScreen->desktop->add_changed(changed.reg); +} + +// PolySegment - changed region is the union of the bounding rects of each +// segment, clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP +// segments, just use the bounding rect of all the segments. + +static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, + xSegment *segs) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, PolySegment); + + if (nseg == 0) { + (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs); + return; + } + + xRectangle regRects[MAX_RECTS_PER_OP]; + int nRegRects = nseg; + + int lw = pGC->lineWidth; + int extra = lw / 2; + + int rectX1, rectY1, rectX2, rectY2; + int minX, minY, maxX, maxY; + + minX = maxX = segs[0].x1; + minY = maxY = segs[0].y1; + + for (int i = 0; i < nseg; i++) { + if (segs[i].x1 > segs[i].x2) { + rectX1 = pDrawable->x + segs[i].x2 - extra; + rectX2 = pDrawable->x + segs[i].x1 + extra + 1; + } else { + rectX1 = pDrawable->x + segs[i].x1 - extra; + rectX2 = pDrawable->x + segs[i].x2 + extra + 1; + } + + if (segs[i].y1 > segs[i].y2) { + rectY1 = pDrawable->y + segs[i].y2 - extra; + rectY2 = pDrawable->y + segs[i].y1 + extra + 1; + } else { + rectY1 = pDrawable->y + segs[i].y1 - extra; + rectY2 = pDrawable->y + segs[i].y2 + extra + 1; + } + + if (nseg <= MAX_RECTS_PER_OP) { + regRects[i].x = rectX1; + regRects[i].y = rectY1; + regRects[i].width = rectX2 - rectX1; + regRects[i].height = rectY2 - rectY1; + } else { + if (rectX1 < minX) minX = rectX1; + if (rectY1 < minY) minY = rectY1; + if (rectX2 > maxX) maxX = rectX2; + if (rectY2 > maxY) maxY = rectY2; + } + } + + if (nseg > MAX_RECTS_PER_OP) { + regRects[0].x = minX; + regRects[0].y = minY; + regRects[0].width = maxX - minX; + regRects[0].height = maxY - minY; + nRegRects = 1; + } + + RegionHelper changed(pScreen, nRegRects, regRects); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs); + + vncHooksScreen->desktop->add_changed(changed.reg); +} + +// PolyRectangle - changed region is the union of the bounding rects around +// each side of the outline rectangles, clipped by pCompositeClip. If there +// are more than MAX_RECTS_PER_OP rectangles, just use the bounding rect of all +// the rectangles. + +static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, + xRectangle *rects) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, PolyRectangle); + + if (nrects == 0) { + (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects); + return; + } + + xRectangle regRects[MAX_RECTS_PER_OP*4]; + int nRegRects = nrects * 4; + + int lw = pGC->lineWidth; + int extra = lw / 2; + + int rectX1, rectY1, rectX2, rectY2; + int minX, minY, maxX, maxY; + + minX = maxX = rects[0].x; + minY = maxY = rects[0].y; + + for (int i = 0; i < nrects; i++) { + if (nrects <= MAX_RECTS_PER_OP) { + regRects[i*4].x = rects[i].x - extra + pDrawable->x; + regRects[i*4].y = rects[i].y - extra + pDrawable->y; + regRects[i*4].width = rects[i].width + 1 + 2 * extra; + regRects[i*4].height = 1 + 2 * extra; + + regRects[i*4+1].x = rects[i].x - extra + pDrawable->x; + regRects[i*4+1].y = rects[i].y - extra + pDrawable->y; + regRects[i*4+1].width = 1 + 2 * extra; + regRects[i*4+1].height = rects[i].height + 1 + 2 * extra; + + regRects[i*4+2].x = rects[i].x + rects[i].width - extra + pDrawable->x; + regRects[i*4+2].y = rects[i].y - extra + pDrawable->y; + regRects[i*4+2].width = 1 + 2 * extra; + regRects[i*4+2].height = rects[i].height + 1 + 2 * extra; + + regRects[i*4+3].x = rects[i].x - extra + pDrawable->x; + regRects[i*4+3].y = rects[i].y + rects[i].height - extra + pDrawable->y; + regRects[i*4+3].width = rects[i].width + 1 + 2 * extra; + regRects[i*4+3].height = 1 + 2 * extra; + } else { + rectX1 = pDrawable->x + rects[i].x - extra; + rectY1 = pDrawable->y + rects[i].y - extra; + rectX2 = pDrawable->x + rects[i].x + rects[i].width + extra+1; + rectY2 = pDrawable->y + rects[i].y + rects[i].height + extra+1; + if (rectX1 < minX) minX = rectX1; + if (rectY1 < minY) minY = rectY1; + if (rectX2 > maxX) maxX = rectX2; + if (rectY2 > maxY) maxY = rectY2; + } + } + + if (nrects > MAX_RECTS_PER_OP) { + regRects[0].x = minX; + regRects[0].y = minY; + regRects[0].width = maxX - minX; + regRects[0].height = maxY - minY; + nRegRects = 1; + } + + RegionHelper changed(pScreen, nRegRects, regRects); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects); + + vncHooksScreen->desktop->add_changed(changed.reg); +} + +// PolyArc - changed region is the union of bounding rects around each arc, +// clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP +// arcs, just use the bounding rect of all the arcs. + +static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, + xArc *arcs) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, PolyArc); + + if (narcs == 0) { + (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs); + return; + } + + xRectangle regRects[MAX_RECTS_PER_OP]; + int nRegRects = narcs; + + int lw = pGC->lineWidth; + if (lw == 0) lw = 1; + int extra = lw / 2; + + int rectX1, rectY1, rectX2, rectY2; + int minX, minY, maxX, maxY; + + minX = maxX = arcs[0].x; + minY = maxY = arcs[0].y; + + for (int i = 0; i < narcs; i++) { + if (narcs <= MAX_RECTS_PER_OP) { + regRects[i].x = arcs[i].x - extra + pDrawable->x; + regRects[i].y = arcs[i].y - extra + pDrawable->y; + regRects[i].width = arcs[i].width + lw; + regRects[i].height = arcs[i].height + lw; + } else { + rectX1 = pDrawable->x + arcs[i].x - extra; + rectY1 = pDrawable->y + arcs[i].y - extra; + rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw; + rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw; + if (rectX1 < minX) minX = rectX1; + if (rectY1 < minY) minY = rectY1; + if (rectX2 > maxX) maxX = rectX2; + if (rectY2 > maxY) maxY = rectY2; + } + } + + if (narcs > MAX_RECTS_PER_OP) { + regRects[0].x = minX; + regRects[0].y = minY; + regRects[0].width = maxX - minX; + regRects[0].height = maxY - minY; + nRegRects = 1; + } + + RegionHelper changed(pScreen, nRegRects, regRects); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs); + + vncHooksScreen->desktop->add_changed(changed.reg); +} + + +// FillPolygon - changed region is the bounding rect around the polygon, +// clipped by pCompositeClip + +static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr pts) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, FillPolygon); + + if (count == 0) { + (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts); + return; + } + + int minX = pts[0].x; + int maxX = pts[0].x; + int minY = pts[0].y; + int maxY = pts[0].y; + + if (mode == CoordModePrevious) { + int x = pts[0].x; + int y = pts[0].y; + + for (int i = 1; i < count; i++) { + x += pts[i].x; + y += pts[i].y; + if (x < minX) minX = x; + if (x > maxX) maxX = x; + if (y < minY) minY = y; + if (y > maxY) maxY = y; + } + } else { + for (int i = 1; i < count; i++) { + if (pts[i].x < minX) minX = pts[i].x; + if (pts[i].x > maxX) maxX = pts[i].x; + if (pts[i].y < minY) minY = pts[i].y; + if (pts[i].y > maxY) maxY = pts[i].y; + } + } + + BoxRec box; + box.x1 = minX + pDrawable->x; + box.y1 = minY + pDrawable->y; + box.x2 = maxX + 1 + pDrawable->x; + box.y2 = maxY + 1 + pDrawable->y; + + RegionHelper changed(pScreen, &box, 0); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts); + + vncHooksScreen->desktop->add_changed(changed.reg); +} + +// PolyFillRect - changed region is the union of the rectangles, clipped by +// pCompositeClip. If there are more than MAX_RECTS_PER_OP rectangles, just +// use the bounding rect of all the rectangles. + +static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects, + xRectangle *rects) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, PolyFillRect); + + if (nrects == 0) { + (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects); + return; + } + + xRectangle regRects[MAX_RECTS_PER_OP]; + int nRegRects = nrects; + int rectX1, rectY1, rectX2, rectY2; + int minX, minY, maxX, maxY; + minX = maxX = rects[0].x; + minY = maxY = rects[0].y; + + for (int i = 0; i < nrects; i++) { + if (nrects <= MAX_RECTS_PER_OP) { + regRects[i].x = rects[i].x + pDrawable->x; + regRects[i].y = rects[i].y + pDrawable->y; + regRects[i].width = rects[i].width; + regRects[i].height = rects[i].height; + } else { + rectX1 = pDrawable->x + rects[i].x; + rectY1 = pDrawable->y + rects[i].y; + rectX2 = pDrawable->x + rects[i].x + rects[i].width; + rectY2 = pDrawable->y + rects[i].y + rects[i].height; + if (rectX1 < minX) minX = rectX1; + if (rectY1 < minY) minY = rectY1; + if (rectX2 > maxX) maxX = rectX2; + if (rectY2 > maxY) maxY = rectY2; + } + } + + if (nrects > MAX_RECTS_PER_OP) { + regRects[0].x = minX; + regRects[0].y = minY; + regRects[0].width = maxX - minX; + regRects[0].height = maxY - minY; + nRegRects = 1; + } + + RegionHelper changed(pScreen, nRegRects, regRects); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects); + + vncHooksScreen->desktop->add_changed(changed.reg); +} + +// PolyFillArc - changed region is the union of bounding rects around each arc, +// clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP arcs, +// just use the bounding rect of all the arcs. + +static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, + xArc *arcs) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, PolyFillArc); + + if (narcs == 0) { + (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs); + return; + } + + xRectangle regRects[MAX_RECTS_PER_OP]; + int nRegRects = narcs; + + int lw = pGC->lineWidth; + if (lw == 0) lw = 1; + int extra = lw / 2; + + int rectX1, rectY1, rectX2, rectY2; + int minX, minY, maxX, maxY; + + minX = maxX = arcs[0].x; + minY = maxY = arcs[0].y; + + for (int i = 0; i < narcs; i++) { + if (narcs <= MAX_RECTS_PER_OP) { + regRects[i].x = arcs[i].x - extra + pDrawable->x; + regRects[i].y = arcs[i].y - extra + pDrawable->y; + regRects[i].width = arcs[i].width + lw; + regRects[i].height = arcs[i].height + lw; + } else { + rectX1 = pDrawable->x + arcs[i].x - extra; + rectY1 = pDrawable->y + arcs[i].y - extra; + rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw; + rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw; + if (rectX1 < minX) minX = rectX1; + if (rectY1 < minY) minY = rectY1; + if (rectX2 > maxX) maxX = rectX2; + if (rectY2 > maxY) maxY = rectY2; + } + } + + if (narcs > MAX_RECTS_PER_OP) { + regRects[0].x = minX; + regRects[0].y = minY; + regRects[0].width = maxX - minX; + regRects[0].height = maxY - minY; + nRegRects = 1; + } + + RegionHelper changed(pScreen, nRegRects, regRects); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs); + + vncHooksScreen->desktop->add_changed(changed.reg); +} + +// GetTextBoundingRect - calculate a bounding rectangle around n chars of a +// font. Not particularly accurate, but good enough. + +static void GetTextBoundingRect(DrawablePtr pDrawable, FontPtr font, int x, + int y, int nchars, BoxPtr box) +{ + int ascent = __rfbmax(FONTASCENT(font), FONTMAXBOUNDS(font, ascent)); + int descent = __rfbmax(FONTDESCENT(font), FONTMAXBOUNDS(font, descent)); + int charWidth = __rfbmax(FONTMAXBOUNDS(font,rightSideBearing), + FONTMAXBOUNDS(font,characterWidth)); + + box->x1 = pDrawable->x + x; + box->y1 = pDrawable->y + y - ascent; + box->x2 = box->x1 + charWidth * nchars; + box->y2 = box->y1 + ascent + descent; + + if (FONTMINBOUNDS(font,leftSideBearing) < 0) + box->x1 += FONTMINBOUNDS(font,leftSideBearing); +} + +// PolyText8 - changed region is bounding rect around count chars, clipped by +// pCompositeClip + +static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int count, char *chars) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, PolyText8); + + if (count == 0) + return (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars); + + BoxRec box; + GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box); + + RegionHelper changed(pScreen, &box, 0); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + int ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars); + + vncHooksScreen->desktop->add_changed(changed.reg); + + return ret; +} + +// PolyText16 - changed region is bounding rect around count chars, clipped by +// pCompositeClip + +static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int count, unsigned short *chars) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, PolyText16); + + if (count == 0) + return (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars); + + BoxRec box; + GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box); + + RegionHelper changed(pScreen, &box, 0); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + int ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars); + + vncHooksScreen->desktop->add_changed(changed.reg); + + return ret; +} + +// ImageText8 - changed region is bounding rect around count chars, clipped by +// pCompositeClip + +static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int count, char *chars) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, ImageText8); + + if (count == 0) { + (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars); + return; + } + + BoxRec box; + GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box); + + RegionHelper changed(pScreen, &box, 0); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars); + + vncHooksScreen->desktop->add_changed(changed.reg); +} + +// ImageText16 - changed region is bounding rect around count chars, clipped by +// pCompositeClip + +static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int count, unsigned short *chars) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, ImageText16); + + if (count == 0) { + (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars); + return; + } + + BoxRec box; + GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box); + + RegionHelper changed(pScreen, &box, 0); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars); + + vncHooksScreen->desktop->add_changed(changed.reg); +} + +// ImageGlyphBlt - changed region is bounding rect around nglyph chars, clipped +// by pCompositeClip + +static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, unsigned int nglyph, + CharInfoPtr *ppci, pointer pglyphBase) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, ImageGlyphBlt); + + if (nglyph == 0) { + (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase); + return; + } + + BoxRec box; + GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box); + + RegionHelper changed(pScreen, &box, 0); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + + vncHooksScreen->desktop->add_changed(changed.reg); +} + +// PolyGlyphBlt - changed region is bounding rect around nglyph chars, clipped +// by pCompositeClip + +static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, unsigned int nglyph, + CharInfoPtr *ppci, pointer pglyphBase) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, PolyGlyphBlt); + + if (nglyph == 0) { + (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase); + return; + } + + BoxRec box; + GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box); + + RegionHelper changed(pScreen, &box, 0); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + + vncHooksScreen->desktop->add_changed(changed.reg); +} + +// PushPixels - changed region is the given rectangle, clipped by +// pCompositeClip + +static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap, + DrawablePtr pDrawable, int w, int h, int x, + int y) +{ + GC_OP_UNWRAPPER(pDrawable, pGC, PushPixels); + + BoxRec box; + box.x1 = x + pDrawable->x; + box.y1 = y + pDrawable->y; + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + + RegionHelper changed(pScreen, &box, 0); + + REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC)); + + (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y); + + vncHooksScreen->desktop->add_changed(changed.reg); +} diff --git a/unix/xc/programs/Xserver/vnc/vncHooks.h b/unix/xc/programs/Xserver/vnc/vncHooks.h new file mode 100644 index 00000000..c556ef3a --- /dev/null +++ b/unix/xc/programs/Xserver/vnc/vncHooks.h @@ -0,0 +1,26 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#ifndef __VNCHOOKS_H__ +#define __VNCHOOKS_H__ + +extern "C" { +#include + extern Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop); +} + +#endif diff --git a/unix/xc/programs/Xserver/vnc/xf86vncModule.cc b/unix/xc/programs/Xserver/vnc/xf86vncModule.cc new file mode 100644 index 00000000..ef8ea506 --- /dev/null +++ b/unix/xc/programs/Xserver/vnc/xf86vncModule.cc @@ -0,0 +1,97 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This 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. + * + * This software is distributed in the hope that 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 software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +/* This is the xf86 module code for the vnc extension. + */ + +#include +#include +#include + +extern "C" { +#define class c_class +#define private c_private +#define bool c_bool +#define new c_new +#include "xf86.h" +#include "xf86Module.h" +#undef class +#undef private +#undef bool +#undef new + +using namespace rfb; + +extern void vncExtensionInit(); +static void vncExtensionInitWithParams(INITARGS); + +#ifdef XFree86LOADER + +static MODULESETUPPROTO(vncSetup); + +ExtensionModule vncExt = +{ + vncExtensionInitWithParams, + "VNC", + NULL, + NULL, + NULL +}; + +static XF86ModuleVersionInfo vncVersRec = +{ + "vnc", + "Constantin Kaplinsky", + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_EXTENSION, /* needs the server extension ABI */ + ABI_EXTENSION_VERSION, + MOD_CLASS_EXTENSION, + {0,0,0,0} +}; + +XF86ModuleData vncModuleData = { &vncVersRec, vncSetup, NULL }; + +static pointer +vncSetup(pointer module, pointer opts, int *errmaj, int *errmin) { + LoadExtension(&vncExt, FALSE); + /* Need a non-NULL return value to indicate success */ + return (pointer)1; +} + +static void vncExtensionInitWithParams(INITARGS) +{ + rfb::initStdIOLoggers(); + rfb::LogWriter::setLogParams("*:stderr:30"); + + for (int scr = 0; scr < screenInfo.numScreens; scr++) { + ScrnInfoPtr pScrn = xf86Screens[scr]; + + for (ParameterIterator i(Configuration::global()); i.param; i.next()) { + char* val = xf86FindOptionValue(pScrn->options, i.param->getName()); + if (val) + i.param->setParam(val); + } + } + + vncExtensionInit(); +} + +#endif /* XFree86LOADER */ +}